From 1dfe08a8c196f13dd1e1da4f5cc29f2c9f357f0d Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:29:13 +0900 Subject: [PATCH 01/20] =?UTF-8?q?feat(misskey-js):=20=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E3=82=92=E5=9E=8B=E3=81=A8=E3=81=97=E3=81=A6=E5=87=BA?= =?UTF-8?q?=E5=8A=9B=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/os.ts | 124 +- packages/frontend/src/scripts/err-promise.ts | 18 + packages/frontend/src/scripts/misskey-api.ts | 13 +- packages/misskey-js/etc/misskey-js.api.md | 1559 +++++++++ .../misskey-js/generator/src/generator.ts | 161 +- packages/misskey-js/src/api.ts | 16 +- packages/misskey-js/src/api.types.ts | 8 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 1528 +++++---- packages/misskey-js/src/autogen/endpoint.ts | 1137 ++++-- .../misskey-js/src/autogen/endpointErrors.ts | 3052 +++++++++++++++++ packages/misskey-js/src/autogen/entities.ts | 381 ++ packages/misskey-js/src/entities.ts | 30 + 12 files changed, 6817 insertions(+), 1210 deletions(-) create mode 100644 packages/frontend/src/scripts/err-promise.ts create mode 100644 packages/misskey-js/src/autogen/endpointErrors.ts diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index f656a52371..4eb4072b72 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -24,55 +24,89 @@ import MkContextMenu from '@/components/MkContextMenu.vue'; import { MenuItem } from '@/types/menu.js'; import copyToClipboard from '@/scripts/copy-to-clipboard.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; +import { ErrPromise } from '@/scripts/err-promise.js'; export const openingWindowsCount = ref(0); -export const apiWithDialog = (( +type CustomErrorDef = { + [key in T extends { code: infer C; } ? C extends string ? C : string : string]?: { title?: string; text: string; }; +}; + +export function apiWithDialog< + E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, + P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], + ER extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], +>( endpoint: E, data: P = {} as any, token?: string | null | undefined, -) => { + customErrors?: CustomErrorDef, +) { const promise = misskeyApi(endpoint, data, token); promiseDialog(promise, null, async (err) => { let title: string | undefined; - let text = err.message + '\n' + err.id; - if (err.code === 'INTERNAL_ERROR') { - title = i18n.ts.internalServerError; - text = i18n.ts.internalServerErrorDescription; - const date = new Date().toISOString(); - const { result } = await actions({ - type: 'error', - title, - text, - actions: [{ - value: 'ok', - text: i18n.ts.gotIt, - primary: true, - }, { - value: 'copy', - text: i18n.ts.copyErrorInfo, - }], - }); - if (result === 'copy') { - copyToClipboard(`Endpoint: ${endpoint}\nInfo: ${JSON.stringify(err.info)}\nDate: ${date}`); - success(); + let text: string; + + const initialText: string[] = []; + if ('message' in err && err.message != null) { + initialText.push(err.message); + } + if ('id' in err && err.id != null) { + initialText.push(err.id); + } + text = initialText.join('\n'); + + if ('code' in err && err.code != null) { + if (err.code === 'INTERNAL_ERROR') { + title = i18n.ts.internalServerError; + text = i18n.ts.internalServerErrorDescription; + const date = new Date().toISOString(); + const { result } = await actions({ + type: 'error', + title, + text, + actions: [{ + value: 'ok', + text: i18n.ts.gotIt, + primary: true, + }, { + value: 'copy', + text: i18n.ts.copyErrorInfo, + }], + }); + if (result === 'copy') { + const text = [ + `Endpoint: ${endpoint}`, + ('info' in err) ? `Info: ${JSON.stringify(err.info)}` : undefined, + `Date: ${date}`, + ].filter(x => x != null); + copyToClipboard(text.join('\n')); + success(); + } + return; + } else if (err.code === 'RATE_LIMIT_EXCEEDED') { + title = i18n.ts.cannotPerformTemporary; + text = i18n.ts.cannotPerformTemporaryDescription; + } else if (err.code === 'INVALID_PARAM') { + title = i18n.ts.invalidParamError; + text = i18n.ts.invalidParamErrorDescription; + } else if (err.code === 'ROLE_PERMISSION_DENIED') { + title = i18n.ts.permissionDeniedError; + text = i18n.ts.permissionDeniedErrorDescription; + } else if (customErrors && customErrors[err.code] != null) { + title = customErrors[err.code].title; + text = customErrors[err.code].text; + } else if (err.code.startsWith('TOO_MANY')) { + title = i18n.ts.youCannotCreateAnymore; + if ('id' in err && err.id != null) { + text = `${i18n.ts.error}: ${err.id}`; + } else { + text = `${i18n.ts.error}`; + } + } else if (err.message.startsWith('Unexpected token')) { + title = i18n.ts.gotInvalidResponseError; + text = i18n.ts.gotInvalidResponseErrorDescription; } - return; - } else if (err.code === 'RATE_LIMIT_EXCEEDED') { - title = i18n.ts.cannotPerformTemporary; - text = i18n.ts.cannotPerformTemporaryDescription; - } else if (err.code === 'INVALID_PARAM') { - title = i18n.ts.invalidParamError; - text = i18n.ts.invalidParamErrorDescription; - } else if (err.code === 'ROLE_PERMISSION_DENIED') { - title = i18n.ts.permissionDeniedError; - text = i18n.ts.permissionDeniedErrorDescription; - } else if (err.code.startsWith('TOO_MANY')) { - title = i18n.ts.youCannotCreateAnymore; - text = `${i18n.ts.error}: ${err.id}`; - } else if (err.message.startsWith('Unexpected token')) { - title = i18n.ts.gotInvalidResponseError; - text = i18n.ts.gotInvalidResponseErrorDescription; } alert({ type: 'error', @@ -82,12 +116,16 @@ export const apiWithDialog = (>( +export function promiseDialog< + T extends ErrPromise | Promise, + R = T extends ErrPromise ? R : T extends Promise ? R : never, + E = T extends ErrPromise ? E : T extends Promise ? any : never, +>( promise: T, - onSuccess?: ((res: any) => void) | null, - onFailure?: ((err: Misskey.api.APIError) => void) | null, + onSuccess?: ((res: R) => void) | null, + onFailure?: ((err: E) => void) | null, text?: string, ): T { const showing = ref(true); diff --git a/packages/frontend/src/scripts/err-promise.ts b/packages/frontend/src/scripts/err-promise.ts new file mode 100644 index 0000000000..1bc6a386ac --- /dev/null +++ b/packages/frontend/src/scripts/err-promise.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + + +export interface IErrPromise { + then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; + + catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; +} + +/** rejectに型付けができるPromise */ +export class ErrPromise extends Promise implements IErrPromise { + constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { + super(executor); + } +} diff --git a/packages/frontend/src/scripts/misskey-api.ts b/packages/frontend/src/scripts/misskey-api.ts index 49fb6f9e59..46d1e049f8 100644 --- a/packages/frontend/src/scripts/misskey-api.ts +++ b/packages/frontend/src/scripts/misskey-api.ts @@ -7,6 +7,7 @@ import * as Misskey from 'misskey-js'; import { ref } from 'vue'; import { apiUrl } from '@/config.js'; import { $i } from '@/account.js'; +import { ErrPromise } from '@/scripts/err-promise.js'; export const pendingApiRequestsCount = ref(0); // Implements Misskey.api.ApiClient.request @@ -14,13 +15,14 @@ export function misskeyApi< ResT = void, E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], + RE extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, >( endpoint: E, data: P = {} as any, token?: string | null | undefined, signal?: AbortSignal, -): Promise<_ResT> { +): ErrPromise<_ResT, RE> { if (endpoint.includes('://')) throw new Error('invalid endpoint'); pendingApiRequestsCount.value++; @@ -28,7 +30,7 @@ export function misskeyApi< pendingApiRequestsCount.value--; }; - const promise = new Promise<_ResT>((resolve, reject) => { + const promise = new ErrPromise<_ResT, RE>((resolve, reject) => { // Append a credential if ($i) (data as any).i = $i.token; if (token !== undefined) (data as any).i = token; @@ -47,7 +49,7 @@ export function misskeyApi< const body = res.status === 204 ? null : await res.json(); if (res.status === 200) { - resolve(body); + resolve(body as _ResT); } else if (res.status === 204) { resolve(undefined as _ResT); // void -> undefined } else { @@ -66,11 +68,12 @@ export function misskeyApiGet< ResT = void, E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], + RE extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, >( endpoint: E, data: P = {} as any, -): Promise<_ResT> { +): ErrPromise<_ResT, RE> { pendingApiRequestsCount.value++; const onFinally = () => { @@ -79,7 +82,7 @@ export function misskeyApiGet< const query = new URLSearchParams(data as any); - const promise = new Promise<_ResT>((resolve, reject) => { + const promise = new ErrPromise<_ResT, RE>((resolve, reject) => { // Send request window.fetch(`${apiUrl}/${endpoint}?${query}`, { method: 'GET', diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index bea89f2a7c..cfb9a48412 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -29,6 +29,11 @@ export { acct } // @public (undocumented) type Ad = components['schemas']['Ad']; +// Warning: (ae-forgotten-export) The symbol "EndpointsErrors" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +type AdminAbuseReportNotificationRecipientCreateErrors = EndpointsErrors['admin___abuse-report___notification-recipient___create'][keyof EndpointsErrors['admin___abuse-report___notification-recipient___create']]; + // Warning: (ae-forgotten-export) The symbol "operations" needs to be exported by the entry point index.d.ts // // @public (undocumented) @@ -37,141 +42,243 @@ type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___ab // @public (undocumented) type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAbuseReportNotificationRecipientDeleteErrors = EndpointsErrors['admin___abuse-report___notification-recipient___delete'][keyof EndpointsErrors['admin___abuse-report___notification-recipient___delete']]; + // @public (undocumented) type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAbuseReportNotificationRecipientListErrors = EndpointsErrors['admin___abuse-report___notification-recipient___list'][keyof EndpointsErrors['admin___abuse-report___notification-recipient___list']]; + // @public (undocumented) type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAbuseReportNotificationRecipientShowErrors = EndpointsErrors['admin___abuse-report___notification-recipient___show'][keyof EndpointsErrors['admin___abuse-report___notification-recipient___show']]; + // @public (undocumented) type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAbuseReportNotificationRecipientUpdateErrors = EndpointsErrors['admin___abuse-report___notification-recipient___update'][keyof EndpointsErrors['admin___abuse-report___notification-recipient___update']]; + // @public (undocumented) type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAbuseUserReportsErrors = EndpointsErrors['admin___abuse-user-reports'][keyof EndpointsErrors['admin___abuse-user-reports']]; + // @public (undocumented) type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAccountsCreateErrors = EndpointsErrors['admin___accounts___create'][keyof EndpointsErrors['admin___accounts___create']]; + // @public (undocumented) type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAccountsDeleteErrors = EndpointsErrors['admin___accounts___delete'][keyof EndpointsErrors['admin___accounts___delete']]; + // @public (undocumented) type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAccountsFindByEmailErrors = EndpointsErrors['admin___accounts___find-by-email'][keyof EndpointsErrors['admin___accounts___find-by-email']]; + // @public (undocumented) type AdminAccountsFindByEmailRequest = operations['admin___accounts___find-by-email']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAccountsFindByEmailResponse = operations['admin___accounts___find-by-email']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAdCreateErrors = EndpointsErrors['admin___ad___create'][keyof EndpointsErrors['admin___ad___create']]; + // @public (undocumented) type AdminAdCreateRequest = operations['admin___ad___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAdCreateResponse = operations['admin___ad___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAdDeleteErrors = EndpointsErrors['admin___ad___delete'][keyof EndpointsErrors['admin___ad___delete']]; + // @public (undocumented) type AdminAdDeleteRequest = operations['admin___ad___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAdListErrors = EndpointsErrors['admin___ad___list'][keyof EndpointsErrors['admin___ad___list']]; + // @public (undocumented) type AdminAdListRequest = operations['admin___ad___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAdListResponse = operations['admin___ad___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAdUpdateErrors = EndpointsErrors['admin___ad___update'][keyof EndpointsErrors['admin___ad___update']]; + // @public (undocumented) type AdminAdUpdateRequest = operations['admin___ad___update']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAnnouncementsCreateErrors = EndpointsErrors['admin___announcements___create'][keyof EndpointsErrors['admin___announcements___create']]; + // @public (undocumented) type AdminAnnouncementsCreateRequest = operations['admin___announcements___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAnnouncementsCreateResponse = operations['admin___announcements___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAnnouncementsDeleteErrors = EndpointsErrors['admin___announcements___delete'][keyof EndpointsErrors['admin___announcements___delete']]; + // @public (undocumented) type AdminAnnouncementsDeleteRequest = operations['admin___announcements___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAnnouncementsListErrors = EndpointsErrors['admin___announcements___list'][keyof EndpointsErrors['admin___announcements___list']]; + // @public (undocumented) type AdminAnnouncementsListRequest = operations['admin___announcements___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAnnouncementsListResponse = operations['admin___announcements___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAnnouncementsUpdateErrors = EndpointsErrors['admin___announcements___update'][keyof EndpointsErrors['admin___announcements___update']]; + // @public (undocumented) type AdminAnnouncementsUpdateRequest = operations['admin___announcements___update']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAvatarDecorationsCreateErrors = EndpointsErrors['admin___avatar-decorations___create'][keyof EndpointsErrors['admin___avatar-decorations___create']]; + // @public (undocumented) type AdminAvatarDecorationsCreateRequest = operations['admin___avatar-decorations___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAvatarDecorationsDeleteErrors = EndpointsErrors['admin___avatar-decorations___delete'][keyof EndpointsErrors['admin___avatar-decorations___delete']]; + // @public (undocumented) type AdminAvatarDecorationsDeleteRequest = operations['admin___avatar-decorations___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminAvatarDecorationsListErrors = EndpointsErrors['admin___avatar-decorations___list'][keyof EndpointsErrors['admin___avatar-decorations___list']]; + // @public (undocumented) type AdminAvatarDecorationsListRequest = operations['admin___avatar-decorations___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminAvatarDecorationsListResponse = operations['admin___avatar-decorations___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminAvatarDecorationsUpdateErrors = EndpointsErrors['admin___avatar-decorations___update'][keyof EndpointsErrors['admin___avatar-decorations___update']]; + // @public (undocumented) type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminDeleteAccountErrors = EndpointsErrors['admin___delete-account'][keyof EndpointsErrors['admin___delete-account']]; + // @public (undocumented) type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminDeleteAllFilesOfAUserErrors = EndpointsErrors['admin___delete-all-files-of-a-user'][keyof EndpointsErrors['admin___delete-all-files-of-a-user']]; + // @public (undocumented) type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminDriveCleanRemoteFilesErrors = EndpointsErrors['admin___drive___clean-remote-files'][keyof EndpointsErrors['admin___drive___clean-remote-files']]; + +// @public (undocumented) +type AdminDriveCleanupErrors = EndpointsErrors['admin___drive___cleanup'][keyof EndpointsErrors['admin___drive___cleanup']]; + +// @public (undocumented) +type AdminDriveFilesErrors = EndpointsErrors['admin___drive___files'][keyof EndpointsErrors['admin___drive___files']]; + // @public (undocumented) type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json']; // @public (undocumented) type AdminDriveFilesResponse = operations['admin___drive___files']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminDriveShowFileErrors = EndpointsErrors['admin___drive___show-file'][keyof EndpointsErrors['admin___drive___show-file']]; + // @public (undocumented) type AdminDriveShowFileRequest = operations['admin___drive___show-file']['requestBody']['content']['application/json']; // @public (undocumented) type AdminDriveShowFileResponse = operations['admin___drive___show-file']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminEmojiAddAliasesBulkErrors = EndpointsErrors['admin___emoji___add-aliases-bulk'][keyof EndpointsErrors['admin___emoji___add-aliases-bulk']]; + // @public (undocumented) type AdminEmojiAddAliasesBulkRequest = operations['admin___emoji___add-aliases-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiAddErrors = EndpointsErrors['admin___emoji___add'][keyof EndpointsErrors['admin___emoji___add']]; + // @public (undocumented) type AdminEmojiAddRequest = operations['admin___emoji___add']['requestBody']['content']['application/json']; // @public (undocumented) type AdminEmojiAddResponse = operations['admin___emoji___add']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminEmojiCopyErrors = EndpointsErrors['admin___emoji___copy'][keyof EndpointsErrors['admin___emoji___copy']]; + // @public (undocumented) type AdminEmojiCopyRequest = operations['admin___emoji___copy']['requestBody']['content']['application/json']; // @public (undocumented) type AdminEmojiCopyResponse = operations['admin___emoji___copy']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminEmojiDeleteBulkErrors = EndpointsErrors['admin___emoji___delete-bulk'][keyof EndpointsErrors['admin___emoji___delete-bulk']]; + // @public (undocumented) type AdminEmojiDeleteBulkRequest = operations['admin___emoji___delete-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiDeleteErrors = EndpointsErrors['admin___emoji___delete'][keyof EndpointsErrors['admin___emoji___delete']]; + // @public (undocumented) type AdminEmojiDeleteRequest = operations['admin___emoji___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiImportZipErrors = EndpointsErrors['admin___emoji___import-zip'][keyof EndpointsErrors['admin___emoji___import-zip']]; + // @public (undocumented) type AdminEmojiImportZipRequest = operations['admin___emoji___import-zip']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiListErrors = EndpointsErrors['admin___emoji___list'][keyof EndpointsErrors['admin___emoji___list']]; + +// @public (undocumented) +type AdminEmojiListRemoteErrors = EndpointsErrors['admin___emoji___list-remote'][keyof EndpointsErrors['admin___emoji___list-remote']]; + // @public (undocumented) type AdminEmojiListRemoteRequest = operations['admin___emoji___list-remote']['requestBody']['content']['application/json']; @@ -184,198 +291,351 @@ type AdminEmojiListRequest = operations['admin___emoji___list']['requestBody'][' // @public (undocumented) type AdminEmojiListResponse = operations['admin___emoji___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminEmojiRemoveAliasesBulkErrors = EndpointsErrors['admin___emoji___remove-aliases-bulk'][keyof EndpointsErrors['admin___emoji___remove-aliases-bulk']]; + // @public (undocumented) type AdminEmojiRemoveAliasesBulkRequest = operations['admin___emoji___remove-aliases-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiSetAliasesBulkErrors = EndpointsErrors['admin___emoji___set-aliases-bulk'][keyof EndpointsErrors['admin___emoji___set-aliases-bulk']]; + // @public (undocumented) type AdminEmojiSetAliasesBulkRequest = operations['admin___emoji___set-aliases-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiSetCategoryBulkErrors = EndpointsErrors['admin___emoji___set-category-bulk'][keyof EndpointsErrors['admin___emoji___set-category-bulk']]; + // @public (undocumented) type AdminEmojiSetCategoryBulkRequest = operations['admin___emoji___set-category-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiSetLicenseBulkErrors = EndpointsErrors['admin___emoji___set-license-bulk'][keyof EndpointsErrors['admin___emoji___set-license-bulk']]; + // @public (undocumented) type AdminEmojiSetLicenseBulkRequest = operations['admin___emoji___set-license-bulk']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminEmojiUpdateErrors = EndpointsErrors['admin___emoji___update'][keyof EndpointsErrors['admin___emoji___update']]; + // @public (undocumented) type AdminEmojiUpdateRequest = operations['admin___emoji___update']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminFederationDeleteAllFilesErrors = EndpointsErrors['admin___federation___delete-all-files'][keyof EndpointsErrors['admin___federation___delete-all-files']]; + // @public (undocumented) type AdminFederationDeleteAllFilesRequest = operations['admin___federation___delete-all-files']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminFederationRefreshRemoteInstanceMetadataErrors = EndpointsErrors['admin___federation___refresh-remote-instance-metadata'][keyof EndpointsErrors['admin___federation___refresh-remote-instance-metadata']]; + // @public (undocumented) type AdminFederationRefreshRemoteInstanceMetadataRequest = operations['admin___federation___refresh-remote-instance-metadata']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminFederationRemoveAllFollowingErrors = EndpointsErrors['admin___federation___remove-all-following'][keyof EndpointsErrors['admin___federation___remove-all-following']]; + // @public (undocumented) type AdminFederationRemoveAllFollowingRequest = operations['admin___federation___remove-all-following']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminFederationUpdateInstanceErrors = EndpointsErrors['admin___federation___update-instance'][keyof EndpointsErrors['admin___federation___update-instance']]; + // @public (undocumented) type AdminFederationUpdateInstanceRequest = operations['admin___federation___update-instance']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminGetIndexStatsErrors = EndpointsErrors['admin___get-index-stats'][keyof EndpointsErrors['admin___get-index-stats']]; + // @public (undocumented) type AdminGetIndexStatsResponse = operations['admin___get-index-stats']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminGetTableStatsErrors = EndpointsErrors['admin___get-table-stats'][keyof EndpointsErrors['admin___get-table-stats']]; + // @public (undocumented) type AdminGetTableStatsResponse = operations['admin___get-table-stats']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminGetUserIpsErrors = EndpointsErrors['admin___get-user-ips'][keyof EndpointsErrors['admin___get-user-ips']]; + // @public (undocumented) type AdminGetUserIpsRequest = operations['admin___get-user-ips']['requestBody']['content']['application/json']; // @public (undocumented) type AdminGetUserIpsResponse = operations['admin___get-user-ips']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminInviteCreateErrors = EndpointsErrors['admin___invite___create'][keyof EndpointsErrors['admin___invite___create']]; + // @public (undocumented) type AdminInviteCreateRequest = operations['admin___invite___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminInviteCreateResponse = operations['admin___invite___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminInviteListErrors = EndpointsErrors['admin___invite___list'][keyof EndpointsErrors['admin___invite___list']]; + // @public (undocumented) type AdminInviteListRequest = operations['admin___invite___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminInviteListResponse = operations['admin___invite___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminMetaErrors = EndpointsErrors['admin___meta'][keyof EndpointsErrors['admin___meta']]; + // @public (undocumented) type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminPromoCreateErrors = EndpointsErrors['admin___promo___create'][keyof EndpointsErrors['admin___promo___create']]; + // @public (undocumented) type AdminPromoCreateRequest = operations['admin___promo___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminQueueClearErrors = EndpointsErrors['admin___queue___clear'][keyof EndpointsErrors['admin___queue___clear']]; + +// @public (undocumented) +type AdminQueueDeliverDelayedErrors = EndpointsErrors['admin___queue___deliver-delayed'][keyof EndpointsErrors['admin___queue___deliver-delayed']]; + // @public (undocumented) type AdminQueueDeliverDelayedResponse = operations['admin___queue___deliver-delayed']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminQueueInboxDelayedErrors = EndpointsErrors['admin___queue___inbox-delayed'][keyof EndpointsErrors['admin___queue___inbox-delayed']]; + // @public (undocumented) type AdminQueueInboxDelayedResponse = operations['admin___queue___inbox-delayed']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminQueuePromoteErrors = EndpointsErrors['admin___queue___promote'][keyof EndpointsErrors['admin___queue___promote']]; + // @public (undocumented) type AdminQueuePromoteRequest = operations['admin___queue___promote']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminQueueStatsErrors = EndpointsErrors['admin___queue___stats'][keyof EndpointsErrors['admin___queue___stats']]; + // @public (undocumented) type AdminQueueStatsResponse = operations['admin___queue___stats']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRelaysAddErrors = EndpointsErrors['admin___relays___add'][keyof EndpointsErrors['admin___relays___add']]; + // @public (undocumented) type AdminRelaysAddRequest = operations['admin___relays___add']['requestBody']['content']['application/json']; // @public (undocumented) type AdminRelaysAddResponse = operations['admin___relays___add']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRelaysListErrors = EndpointsErrors['admin___relays___list'][keyof EndpointsErrors['admin___relays___list']]; + // @public (undocumented) type AdminRelaysListResponse = operations['admin___relays___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRelaysRemoveErrors = EndpointsErrors['admin___relays___remove'][keyof EndpointsErrors['admin___relays___remove']]; + // @public (undocumented) type AdminRelaysRemoveRequest = operations['admin___relays___remove']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminResetPasswordErrors = EndpointsErrors['admin___reset-password'][keyof EndpointsErrors['admin___reset-password']]; + // @public (undocumented) type AdminResetPasswordRequest = operations['admin___reset-password']['requestBody']['content']['application/json']; // @public (undocumented) type AdminResetPasswordResponse = operations['admin___reset-password']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminResolveAbuseUserReportErrors = EndpointsErrors['admin___resolve-abuse-user-report'][keyof EndpointsErrors['admin___resolve-abuse-user-report']]; + // @public (undocumented) type AdminResolveAbuseUserReportRequest = operations['admin___resolve-abuse-user-report']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesAssignErrors = EndpointsErrors['admin___roles___assign'][keyof EndpointsErrors['admin___roles___assign']]; + // @public (undocumented) type AdminRolesAssignRequest = operations['admin___roles___assign']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesCreateErrors = EndpointsErrors['admin___roles___create'][keyof EndpointsErrors['admin___roles___create']]; + // @public (undocumented) type AdminRolesCreateRequest = operations['admin___roles___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminRolesCreateResponse = operations['admin___roles___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRolesDeleteErrors = EndpointsErrors['admin___roles___delete'][keyof EndpointsErrors['admin___roles___delete']]; + // @public (undocumented) type AdminRolesDeleteRequest = operations['admin___roles___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesListErrors = EndpointsErrors['admin___roles___list'][keyof EndpointsErrors['admin___roles___list']]; + // @public (undocumented) type AdminRolesListResponse = operations['admin___roles___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRolesShowErrors = EndpointsErrors['admin___roles___show'][keyof EndpointsErrors['admin___roles___show']]; + // @public (undocumented) type AdminRolesShowRequest = operations['admin___roles___show']['requestBody']['content']['application/json']; // @public (undocumented) type AdminRolesShowResponse = operations['admin___roles___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminRolesUnassignErrors = EndpointsErrors['admin___roles___unassign'][keyof EndpointsErrors['admin___roles___unassign']]; + // @public (undocumented) type AdminRolesUnassignRequest = operations['admin___roles___unassign']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesUpdateDefaultPoliciesErrors = EndpointsErrors['admin___roles___update-default-policies'][keyof EndpointsErrors['admin___roles___update-default-policies']]; + // @public (undocumented) type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesUpdateErrors = EndpointsErrors['admin___roles___update'][keyof EndpointsErrors['admin___roles___update']]; + // @public (undocumented) type AdminRolesUpdateRequest = operations['admin___roles___update']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminRolesUsersErrors = EndpointsErrors['admin___roles___users'][keyof EndpointsErrors['admin___roles___users']]; + // @public (undocumented) type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json']; // @public (undocumented) type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminSendEmailErrors = EndpointsErrors['admin___send-email'][keyof EndpointsErrors['admin___send-email']]; + // @public (undocumented) type AdminSendEmailRequest = operations['admin___send-email']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminServerInfoErrors = EndpointsErrors['admin___server-info'][keyof EndpointsErrors['admin___server-info']]; + // @public (undocumented) type AdminServerInfoResponse = operations['admin___server-info']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminShowModerationLogsErrors = EndpointsErrors['admin___show-moderation-logs'][keyof EndpointsErrors['admin___show-moderation-logs']]; + // @public (undocumented) type AdminShowModerationLogsRequest = operations['admin___show-moderation-logs']['requestBody']['content']['application/json']; // @public (undocumented) type AdminShowModerationLogsResponse = operations['admin___show-moderation-logs']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminShowUserErrors = EndpointsErrors['admin___show-user'][keyof EndpointsErrors['admin___show-user']]; + // @public (undocumented) type AdminShowUserRequest = operations['admin___show-user']['requestBody']['content']['application/json']; // @public (undocumented) type AdminShowUserResponse = operations['admin___show-user']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminShowUsersErrors = EndpointsErrors['admin___show-users'][keyof EndpointsErrors['admin___show-users']]; + // @public (undocumented) type AdminShowUsersRequest = operations['admin___show-users']['requestBody']['content']['application/json']; // @public (undocumented) type AdminShowUsersResponse = operations['admin___show-users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminSuspendUserErrors = EndpointsErrors['admin___suspend-user'][keyof EndpointsErrors['admin___suspend-user']]; + // @public (undocumented) type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookCreateErrors = EndpointsErrors['admin___system-webhook___create'][keyof EndpointsErrors['admin___system-webhook___create']]; + // @public (undocumented) type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; // @public (undocumented) type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookDeleteErrors = EndpointsErrors['admin___system-webhook___delete'][keyof EndpointsErrors['admin___system-webhook___delete']]; + // @public (undocumented) type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookListErrors = EndpointsErrors['admin___system-webhook___list'][keyof EndpointsErrors['admin___system-webhook___list']]; + // @public (undocumented) type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; // @public (undocumented) type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookShowErrors = EndpointsErrors['admin___system-webhook___show'][keyof EndpointsErrors['admin___system-webhook___show']]; + // @public (undocumented) type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; // @public (undocumented) type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookUpdateErrors = EndpointsErrors['admin___system-webhook___update'][keyof EndpointsErrors['admin___system-webhook___update']]; + // @public (undocumented) type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; // @public (undocumented) type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminUnsetUserAvatarErrors = EndpointsErrors['admin___unset-user-avatar'][keyof EndpointsErrors['admin___unset-user-avatar']]; + // @public (undocumented) type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminUnsetUserBannerErrors = EndpointsErrors['admin___unset-user-banner'][keyof EndpointsErrors['admin___unset-user-banner']]; + // @public (undocumented) type AdminUnsetUserBannerRequest = operations['admin___unset-user-banner']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminUnsuspendUserErrors = EndpointsErrors['admin___unsuspend-user'][keyof EndpointsErrors['admin___unsuspend-user']]; + // @public (undocumented) type AdminUnsuspendUserRequest = operations['admin___unsuspend-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminUpdateMetaErrors = EndpointsErrors['admin___update-meta'][keyof EndpointsErrors['admin___update-meta']]; + // @public (undocumented) type AdminUpdateMetaRequest = operations['admin___update-meta']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminUpdateUserNoteErrors = EndpointsErrors['admin___update-user-note'][keyof EndpointsErrors['admin___update-user-note']]; + // @public (undocumented) type AdminUpdateUserNoteRequest = operations['admin___update-user-note']['requestBody']['content']['application/json']; @@ -387,12 +647,18 @@ type AnnouncementCreated = { announcement: Announcement; }; +// @public (undocumented) +type AnnouncementsErrors = EndpointsErrors['announcements'][keyof EndpointsErrors['announcements']]; + // @public (undocumented) type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json']; // @public (undocumented) type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AnnouncementsShowErrors = EndpointsErrors['announcements___show'][keyof EndpointsErrors['announcements___show']]; + // @public (undocumented) type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json']; @@ -402,36 +668,57 @@ type AnnouncementsShowResponse = operations['announcements___show']['responses'] // @public (undocumented) type Antenna = components['schemas']['Antenna']; +// @public (undocumented) +type AntennasCreateErrors = EndpointsErrors['antennas___create'][keyof EndpointsErrors['antennas___create']]; + // @public (undocumented) type AntennasCreateRequest = operations['antennas___create']['requestBody']['content']['application/json']; // @public (undocumented) type AntennasCreateResponse = operations['antennas___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AntennasDeleteErrors = EndpointsErrors['antennas___delete'][keyof EndpointsErrors['antennas___delete']]; + // @public (undocumented) type AntennasDeleteRequest = operations['antennas___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type AntennasListErrors = EndpointsErrors['antennas___list'][keyof EndpointsErrors['antennas___list']]; + // @public (undocumented) type AntennasListResponse = operations['antennas___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AntennasNotesErrors = EndpointsErrors['antennas___notes'][keyof EndpointsErrors['antennas___notes']]; + // @public (undocumented) type AntennasNotesRequest = operations['antennas___notes']['requestBody']['content']['application/json']; // @public (undocumented) type AntennasNotesResponse = operations['antennas___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AntennasShowErrors = EndpointsErrors['antennas___show'][keyof EndpointsErrors['antennas___show']]; + // @public (undocumented) type AntennasShowRequest = operations['antennas___show']['requestBody']['content']['application/json']; // @public (undocumented) type AntennasShowResponse = operations['antennas___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AntennasUpdateErrors = EndpointsErrors['antennas___update'][keyof EndpointsErrors['antennas___update']]; + // @public (undocumented) type AntennasUpdateRequest = operations['antennas___update']['requestBody']['content']['application/json']; // @public (undocumented) type AntennasUpdateResponse = operations['antennas___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ApGetErrors = EndpointsErrors['ap___get'][keyof EndpointsErrors['ap___get']]; + // @public (undocumented) type ApGetRequest = operations['ap___get']['requestBody']['content']['application/json']; @@ -476,39 +763,60 @@ type APIError = { // @public (undocumented) type App = components['schemas']['App']; +// @public (undocumented) +type AppCreateErrors = EndpointsErrors['app___create'][keyof EndpointsErrors['app___create']]; + // @public (undocumented) type AppCreateRequest = operations['app___create']['requestBody']['content']['application/json']; // @public (undocumented) type AppCreateResponse = operations['app___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AppShowErrors = EndpointsErrors['app___show'][keyof EndpointsErrors['app___show']]; + // @public (undocumented) type AppShowRequest = operations['app___show']['requestBody']['content']['application/json']; // @public (undocumented) type AppShowResponse = operations['app___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ApShowErrors = EndpointsErrors['ap___show'][keyof EndpointsErrors['ap___show']]; + // @public (undocumented) type ApShowRequest = operations['ap___show']['requestBody']['content']['application/json']; // @public (undocumented) type ApShowResponse = operations['ap___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AuthAcceptErrors = EndpointsErrors['auth___accept'][keyof EndpointsErrors['auth___accept']]; + // @public (undocumented) type AuthAcceptRequest = operations['auth___accept']['requestBody']['content']['application/json']; +// @public (undocumented) +type AuthSessionGenerateErrors = EndpointsErrors['auth___session___generate'][keyof EndpointsErrors['auth___session___generate']]; + // @public (undocumented) type AuthSessionGenerateRequest = operations['auth___session___generate']['requestBody']['content']['application/json']; // @public (undocumented) type AuthSessionGenerateResponse = operations['auth___session___generate']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AuthSessionShowErrors = EndpointsErrors['auth___session___show'][keyof EndpointsErrors['auth___session___show']]; + // @public (undocumented) type AuthSessionShowRequest = operations['auth___session___show']['requestBody']['content']['application/json']; // @public (undocumented) type AuthSessionShowResponse = operations['auth___session___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AuthSessionUserkeyErrors = EndpointsErrors['auth___session___userkey'][keyof EndpointsErrors['auth___session___userkey']]; + // @public (undocumented) type AuthSessionUserkeyRequest = operations['auth___session___userkey']['requestBody']['content']['application/json']; @@ -518,30 +826,45 @@ type AuthSessionUserkeyResponse = operations['auth___session___userkey']['respon // @public (undocumented) type Blocking = components['schemas']['Blocking']; +// @public (undocumented) +type BlockingCreateErrors = EndpointsErrors['blocking___create'][keyof EndpointsErrors['blocking___create']]; + // @public (undocumented) type BlockingCreateRequest = operations['blocking___create']['requestBody']['content']['application/json']; // @public (undocumented) type BlockingCreateResponse = operations['blocking___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type BlockingDeleteErrors = EndpointsErrors['blocking___delete'][keyof EndpointsErrors['blocking___delete']]; + // @public (undocumented) type BlockingDeleteRequest = operations['blocking___delete']['requestBody']['content']['application/json']; // @public (undocumented) type BlockingDeleteResponse = operations['blocking___delete']['responses']['200']['content']['application/json']; +// @public (undocumented) +type BlockingListErrors = EndpointsErrors['blocking___list'][keyof EndpointsErrors['blocking___list']]; + // @public (undocumented) type BlockingListRequest = operations['blocking___list']['requestBody']['content']['application/json']; // @public (undocumented) type BlockingListResponse = operations['blocking___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type BubbleGameRankingErrors = EndpointsErrors['bubble-game___ranking'][keyof EndpointsErrors['bubble-game___ranking']]; + // @public (undocumented) type BubbleGameRankingRequest = operations['bubble-game___ranking']['requestBody']['content']['application/json']; // @public (undocumented) type BubbleGameRankingResponse = operations['bubble-game___ranking']['responses']['200']['content']['application/json']; +// @public (undocumented) +type BubbleGameRegisterErrors = EndpointsErrors['bubble-game___register'][keyof EndpointsErrors['bubble-game___register']]; + // @public (undocumented) type BubbleGameRegisterRequest = operations['bubble-game___register']['requestBody']['content']['application/json']; @@ -794,132 +1117,207 @@ export type Channels = { }; }; +// @public (undocumented) +type ChannelsCreateErrors = EndpointsErrors['channels___create'][keyof EndpointsErrors['channels___create']]; + // @public (undocumented) type ChannelsCreateRequest = operations['channels___create']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsCreateResponse = operations['channels___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsFavoriteErrors = EndpointsErrors['channels___favorite'][keyof EndpointsErrors['channels___favorite']]; + // @public (undocumented) type ChannelsFavoriteRequest = operations['channels___favorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type ChannelsFeaturedErrors = EndpointsErrors['channels___featured'][keyof EndpointsErrors['channels___featured']]; + // @public (undocumented) type ChannelsFeaturedResponse = operations['channels___featured']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsFollowedErrors = EndpointsErrors['channels___followed'][keyof EndpointsErrors['channels___followed']]; + // @public (undocumented) type ChannelsFollowedRequest = operations['channels___followed']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsFollowedResponse = operations['channels___followed']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsFollowErrors = EndpointsErrors['channels___follow'][keyof EndpointsErrors['channels___follow']]; + // @public (undocumented) type ChannelsFollowRequest = operations['channels___follow']['requestBody']['content']['application/json']; +// @public (undocumented) +type ChannelsMyFavoritesErrors = EndpointsErrors['channels___my-favorites'][keyof EndpointsErrors['channels___my-favorites']]; + // @public (undocumented) type ChannelsMyFavoritesResponse = operations['channels___my-favorites']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsOwnedErrors = EndpointsErrors['channels___owned'][keyof EndpointsErrors['channels___owned']]; + // @public (undocumented) type ChannelsOwnedRequest = operations['channels___owned']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsOwnedResponse = operations['channels___owned']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsSearchErrors = EndpointsErrors['channels___search'][keyof EndpointsErrors['channels___search']]; + // @public (undocumented) type ChannelsSearchRequest = operations['channels___search']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsSearchResponse = operations['channels___search']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsShowErrors = EndpointsErrors['channels___show'][keyof EndpointsErrors['channels___show']]; + // @public (undocumented) type ChannelsShowRequest = operations['channels___show']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsShowResponse = operations['channels___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsTimelineErrors = EndpointsErrors['channels___timeline'][keyof EndpointsErrors['channels___timeline']]; + // @public (undocumented) type ChannelsTimelineRequest = operations['channels___timeline']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsTimelineResponse = operations['channels___timeline']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChannelsUnfavoriteErrors = EndpointsErrors['channels___unfavorite'][keyof EndpointsErrors['channels___unfavorite']]; + // @public (undocumented) type ChannelsUnfavoriteRequest = operations['channels___unfavorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type ChannelsUnfollowErrors = EndpointsErrors['channels___unfollow'][keyof EndpointsErrors['channels___unfollow']]; + // @public (undocumented) type ChannelsUnfollowRequest = operations['channels___unfollow']['requestBody']['content']['application/json']; +// @public (undocumented) +type ChannelsUpdateErrors = EndpointsErrors['channels___update'][keyof EndpointsErrors['channels___update']]; + // @public (undocumented) type ChannelsUpdateRequest = operations['channels___update']['requestBody']['content']['application/json']; // @public (undocumented) type ChannelsUpdateResponse = operations['channels___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsActiveUsersErrors = EndpointsErrors['charts___active-users'][keyof EndpointsErrors['charts___active-users']]; + // @public (undocumented) type ChartsActiveUsersRequest = operations['charts___active-users']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsActiveUsersResponse = operations['charts___active-users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsApRequestErrors = EndpointsErrors['charts___ap-request'][keyof EndpointsErrors['charts___ap-request']]; + // @public (undocumented) type ChartsApRequestRequest = operations['charts___ap-request']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsApRequestResponse = operations['charts___ap-request']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsDriveErrors = EndpointsErrors['charts___drive'][keyof EndpointsErrors['charts___drive']]; + // @public (undocumented) type ChartsDriveRequest = operations['charts___drive']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsDriveResponse = operations['charts___drive']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsFederationErrors = EndpointsErrors['charts___federation'][keyof EndpointsErrors['charts___federation']]; + // @public (undocumented) type ChartsFederationRequest = operations['charts___federation']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsFederationResponse = operations['charts___federation']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsInstanceErrors = EndpointsErrors['charts___instance'][keyof EndpointsErrors['charts___instance']]; + // @public (undocumented) type ChartsInstanceRequest = operations['charts___instance']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsInstanceResponse = operations['charts___instance']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsNotesErrors = EndpointsErrors['charts___notes'][keyof EndpointsErrors['charts___notes']]; + // @public (undocumented) type ChartsNotesRequest = operations['charts___notes']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsNotesResponse = operations['charts___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUserDriveErrors = EndpointsErrors['charts___user___drive'][keyof EndpointsErrors['charts___user___drive']]; + // @public (undocumented) type ChartsUserDriveRequest = operations['charts___user___drive']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsUserDriveResponse = operations['charts___user___drive']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUserFollowingErrors = EndpointsErrors['charts___user___following'][keyof EndpointsErrors['charts___user___following']]; + // @public (undocumented) type ChartsUserFollowingRequest = operations['charts___user___following']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsUserFollowingResponse = operations['charts___user___following']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUserNotesErrors = EndpointsErrors['charts___user___notes'][keyof EndpointsErrors['charts___user___notes']]; + // @public (undocumented) type ChartsUserNotesRequest = operations['charts___user___notes']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsUserNotesResponse = operations['charts___user___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUserPvErrors = EndpointsErrors['charts___user___pv'][keyof EndpointsErrors['charts___user___pv']]; + // @public (undocumented) type ChartsUserPvRequest = operations['charts___user___pv']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsUserPvResponse = operations['charts___user___pv']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUserReactionsErrors = EndpointsErrors['charts___user___reactions'][keyof EndpointsErrors['charts___user___reactions']]; + // @public (undocumented) type ChartsUserReactionsRequest = operations['charts___user___reactions']['requestBody']['content']['application/json']; // @public (undocumented) type ChartsUserReactionsResponse = operations['charts___user___reactions']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ChartsUsersErrors = EndpointsErrors['charts___users'][keyof EndpointsErrors['charts___users']]; + // @public (undocumented) type ChartsUsersRequest = operations['charts___users']['requestBody']['content']['application/json']; @@ -929,45 +1327,78 @@ type ChartsUsersResponse = operations['charts___users']['responses']['200']['con // @public (undocumented) type Clip = components['schemas']['Clip']; +// @public (undocumented) +type ClipsAddNoteErrors = EndpointsErrors['clips___add-note'][keyof EndpointsErrors['clips___add-note']]; + // @public (undocumented) type ClipsAddNoteRequest = operations['clips___add-note']['requestBody']['content']['application/json']; +// @public (undocumented) +type ClipsCreateErrors = EndpointsErrors['clips___create'][keyof EndpointsErrors['clips___create']]; + // @public (undocumented) type ClipsCreateRequest = operations['clips___create']['requestBody']['content']['application/json']; // @public (undocumented) type ClipsCreateResponse = operations['clips___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ClipsDeleteErrors = EndpointsErrors['clips___delete'][keyof EndpointsErrors['clips___delete']]; + // @public (undocumented) type ClipsDeleteRequest = operations['clips___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type ClipsFavoriteErrors = EndpointsErrors['clips___favorite'][keyof EndpointsErrors['clips___favorite']]; + // @public (undocumented) type ClipsFavoriteRequest = operations['clips___favorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type ClipsListErrors = EndpointsErrors['clips___list'][keyof EndpointsErrors['clips___list']]; + // @public (undocumented) type ClipsListResponse = operations['clips___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ClipsMyFavoritesErrors = EndpointsErrors['clips___my-favorites'][keyof EndpointsErrors['clips___my-favorites']]; + // @public (undocumented) type ClipsMyFavoritesResponse = operations['clips___my-favorites']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ClipsNotesErrors = EndpointsErrors['clips___notes'][keyof EndpointsErrors['clips___notes']]; + // @public (undocumented) type ClipsNotesRequest = operations['clips___notes']['requestBody']['content']['application/json']; // @public (undocumented) type ClipsNotesResponse = operations['clips___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ClipsRemoveNoteErrors = EndpointsErrors['clips___remove-note'][keyof EndpointsErrors['clips___remove-note']]; + // @public (undocumented) type ClipsRemoveNoteRequest = operations['clips___remove-note']['requestBody']['content']['application/json']; +// @public (undocumented) +type ClipsShowErrors = EndpointsErrors['clips___show'][keyof EndpointsErrors['clips___show']]; + // @public (undocumented) type ClipsShowRequest = operations['clips___show']['requestBody']['content']['application/json']; // @public (undocumented) type ClipsShowResponse = operations['clips___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ClipsUnfavoriteErrors = EndpointsErrors['clips___unfavorite'][keyof EndpointsErrors['clips___unfavorite']]; + // @public (undocumented) type ClipsUnfavoriteRequest = operations['clips___unfavorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type ClipsUpdateErrors = EndpointsErrors['clips___update'][keyof EndpointsErrors['clips___update']]; + // @public (undocumented) type ClipsUpdateRequest = operations['clips___update']['requestBody']['content']['application/json']; @@ -977,36 +1408,60 @@ type ClipsUpdateResponse = operations['clips___update']['responses']['200']['con // @public (undocumented) type DateString = string; +// @public (undocumented) +type DriveErrors = EndpointsErrors['drive'][keyof EndpointsErrors['drive']]; + // @public (undocumented) type DriveFile = components['schemas']['DriveFile']; +// @public (undocumented) +type DriveFilesAttachedNotesErrors = EndpointsErrors['drive___files___attached-notes'][keyof EndpointsErrors['drive___files___attached-notes']]; + // @public (undocumented) type DriveFilesAttachedNotesRequest = operations['drive___files___attached-notes']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFilesAttachedNotesResponse = operations['drive___files___attached-notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesCheckExistenceErrors = EndpointsErrors['drive___files___check-existence'][keyof EndpointsErrors['drive___files___check-existence']]; + // @public (undocumented) type DriveFilesCheckExistenceRequest = operations['drive___files___check-existence']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFilesCheckExistenceResponse = operations['drive___files___check-existence']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesCreateErrors = EndpointsErrors['drive___files___create'][keyof EndpointsErrors['drive___files___create']]; + // @public (undocumented) type DriveFilesCreateRequest = operations['drive___files___create']['requestBody']['content']['multipart/form-data']; // @public (undocumented) type DriveFilesCreateResponse = operations['drive___files___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesDeleteErrors = EndpointsErrors['drive___files___delete'][keyof EndpointsErrors['drive___files___delete']]; + // @public (undocumented) type DriveFilesDeleteRequest = operations['drive___files___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type DriveFilesErrors = EndpointsErrors['drive___files'][keyof EndpointsErrors['drive___files']]; + +// @public (undocumented) +type DriveFilesFindByHashErrors = EndpointsErrors['drive___files___find-by-hash'][keyof EndpointsErrors['drive___files___find-by-hash']]; + // @public (undocumented) type DriveFilesFindByHashRequest = operations['drive___files___find-by-hash']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFilesFindByHashResponse = operations['drive___files___find-by-hash']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesFindErrors = EndpointsErrors['drive___files___find'][keyof EndpointsErrors['drive___files___find']]; + // @public (undocumented) type DriveFilesFindRequest = operations['drive___files___find']['requestBody']['content']['application/json']; @@ -1019,33 +1474,54 @@ type DriveFilesRequest = operations['drive___files']['requestBody']['content'][' // @public (undocumented) type DriveFilesResponse = operations['drive___files']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesShowErrors = EndpointsErrors['drive___files___show'][keyof EndpointsErrors['drive___files___show']]; + // @public (undocumented) type DriveFilesShowRequest = operations['drive___files___show']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFilesShowResponse = operations['drive___files___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesUpdateErrors = EndpointsErrors['drive___files___update'][keyof EndpointsErrors['drive___files___update']]; + // @public (undocumented) type DriveFilesUpdateRequest = operations['drive___files___update']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFilesUpdateResponse = operations['drive___files___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFilesUploadFromUrlErrors = EndpointsErrors['drive___files___upload-from-url'][keyof EndpointsErrors['drive___files___upload-from-url']]; + // @public (undocumented) type DriveFilesUploadFromUrlRequest = operations['drive___files___upload-from-url']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFolder = components['schemas']['DriveFolder']; +// @public (undocumented) +type DriveFoldersCreateErrors = EndpointsErrors['drive___folders___create'][keyof EndpointsErrors['drive___folders___create']]; + // @public (undocumented) type DriveFoldersCreateRequest = operations['drive___folders___create']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFoldersCreateResponse = operations['drive___folders___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFoldersDeleteErrors = EndpointsErrors['drive___folders___delete'][keyof EndpointsErrors['drive___folders___delete']]; + // @public (undocumented) type DriveFoldersDeleteRequest = operations['drive___folders___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type DriveFoldersErrors = EndpointsErrors['drive___folders'][keyof EndpointsErrors['drive___folders']]; + +// @public (undocumented) +type DriveFoldersFindErrors = EndpointsErrors['drive___folders___find'][keyof EndpointsErrors['drive___folders___find']]; + // @public (undocumented) type DriveFoldersFindRequest = operations['drive___folders___find']['requestBody']['content']['application/json']; @@ -1058,12 +1534,18 @@ type DriveFoldersRequest = operations['drive___folders']['requestBody']['content // @public (undocumented) type DriveFoldersResponse = operations['drive___folders']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFoldersShowErrors = EndpointsErrors['drive___folders___show'][keyof EndpointsErrors['drive___folders___show']]; + // @public (undocumented) type DriveFoldersShowRequest = operations['drive___folders___show']['requestBody']['content']['application/json']; // @public (undocumented) type DriveFoldersShowResponse = operations['drive___folders___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveFoldersUpdateErrors = EndpointsErrors['drive___folders___update'][keyof EndpointsErrors['drive___folders___update']]; + // @public (undocumented) type DriveFoldersUpdateRequest = operations['drive___folders___update']['requestBody']['content']['application/json']; @@ -1073,12 +1555,18 @@ type DriveFoldersUpdateResponse = operations['drive___folders___update']['respon // @public (undocumented) type DriveResponse = operations['drive']['responses']['200']['content']['application/json']; +// @public (undocumented) +type DriveStreamErrors = EndpointsErrors['drive___stream'][keyof EndpointsErrors['drive___stream']]; + // @public (undocumented) type DriveStreamRequest = operations['drive___stream']['requestBody']['content']['application/json']; // @public (undocumented) type DriveStreamResponse = operations['drive___stream']['responses']['200']['content']['application/json']; +// @public (undocumented) +type EmailAddressAvailableErrors = EndpointsErrors['email-address___available'][keyof EndpointsErrors['email-address___available']]; + // @public (undocumented) type EmailAddressAvailableRequest = operations['email-address___available']['requestBody']['content']['application/json']; @@ -1098,12 +1586,18 @@ type EmojiDeleted = { // @public (undocumented) type EmojiDetailed = components['schemas']['EmojiDetailed']; +// @public (undocumented) +type EmojiErrors = EndpointsErrors['emoji'][keyof EndpointsErrors['emoji']]; + // @public (undocumented) type EmojiRequest = operations['emoji']['requestBody']['content']['application/json']; // @public (undocumented) type EmojiResponse = operations['emoji']['responses']['200']['content']['application/json']; +// @public (undocumented) +type EmojisErrors = EndpointsErrors['emojis'][keyof EndpointsErrors['emojis']]; + // @public (undocumented) type EmojiSimple = components['schemas']['EmojiSimple']; @@ -1115,12 +1609,18 @@ type EmojiUpdated = { emojis: EmojiDetailed[]; }; +// @public (undocumented) +type EmptyErrors = Record | undefined; + // @public (undocumented) type EmptyRequest = Record | undefined; // @public (undocumented) type EmptyResponse = Record | undefined; +// @public (undocumented) +type EndpointErrors = EndpointsErrors['endpoint'][keyof EndpointsErrors['endpoint']]; + // @public (undocumented) type EndpointRequest = operations['endpoint']['requestBody']['content']['application/json']; @@ -1147,21 +1647,28 @@ export type Endpoints = Overwrite; +// @public (undocumented) +type EndpointsErrors_2 = EndpointsErrors['endpoints'][keyof EndpointsErrors['endpoints']]; + // @public (undocumented) type EndpointsResponse = operations['endpoints']['responses']['200']['content']['application/json']; @@ -1183,580 +1690,962 @@ declare namespace entities { SignupResponse, SignupPendingRequest, SignupPendingResponse, + SignupErrors, SigninRequest, SigninResponse, + SigninErrors, EmptyRequest, EmptyResponse, + EmptyErrors, AdminMetaResponse, + AdminMetaErrors, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, + AdminAbuseUserReportsErrors, AdminAbuseReportNotificationRecipientListRequest, AdminAbuseReportNotificationRecipientListResponse, + AdminAbuseReportNotificationRecipientListErrors, AdminAbuseReportNotificationRecipientShowRequest, AdminAbuseReportNotificationRecipientShowResponse, + AdminAbuseReportNotificationRecipientShowErrors, AdminAbuseReportNotificationRecipientCreateRequest, AdminAbuseReportNotificationRecipientCreateResponse, + AdminAbuseReportNotificationRecipientCreateErrors, AdminAbuseReportNotificationRecipientUpdateRequest, AdminAbuseReportNotificationRecipientUpdateResponse, + AdminAbuseReportNotificationRecipientUpdateErrors, AdminAbuseReportNotificationRecipientDeleteRequest, + AdminAbuseReportNotificationRecipientDeleteErrors, AdminAccountsCreateRequest, AdminAccountsCreateResponse, + AdminAccountsCreateErrors, AdminAccountsDeleteRequest, + AdminAccountsDeleteErrors, AdminAccountsFindByEmailRequest, AdminAccountsFindByEmailResponse, + AdminAccountsFindByEmailErrors, AdminAdCreateRequest, AdminAdCreateResponse, + AdminAdCreateErrors, AdminAdDeleteRequest, + AdminAdDeleteErrors, AdminAdListRequest, AdminAdListResponse, + AdminAdListErrors, AdminAdUpdateRequest, + AdminAdUpdateErrors, AdminAnnouncementsCreateRequest, AdminAnnouncementsCreateResponse, + AdminAnnouncementsCreateErrors, AdminAnnouncementsDeleteRequest, + AdminAnnouncementsDeleteErrors, AdminAnnouncementsListRequest, AdminAnnouncementsListResponse, + AdminAnnouncementsListErrors, AdminAnnouncementsUpdateRequest, + AdminAnnouncementsUpdateErrors, AdminAvatarDecorationsCreateRequest, + AdminAvatarDecorationsCreateErrors, AdminAvatarDecorationsDeleteRequest, + AdminAvatarDecorationsDeleteErrors, AdminAvatarDecorationsListRequest, AdminAvatarDecorationsListResponse, + AdminAvatarDecorationsListErrors, AdminAvatarDecorationsUpdateRequest, + AdminAvatarDecorationsUpdateErrors, AdminDeleteAllFilesOfAUserRequest, + AdminDeleteAllFilesOfAUserErrors, AdminUnsetUserAvatarRequest, + AdminUnsetUserAvatarErrors, AdminUnsetUserBannerRequest, + AdminUnsetUserBannerErrors, + AdminDriveCleanRemoteFilesErrors, + AdminDriveCleanupErrors, AdminDriveFilesRequest, AdminDriveFilesResponse, + AdminDriveFilesErrors, AdminDriveShowFileRequest, AdminDriveShowFileResponse, + AdminDriveShowFileErrors, AdminEmojiAddAliasesBulkRequest, + AdminEmojiAddAliasesBulkErrors, AdminEmojiAddRequest, AdminEmojiAddResponse, + AdminEmojiAddErrors, AdminEmojiCopyRequest, AdminEmojiCopyResponse, + AdminEmojiCopyErrors, AdminEmojiDeleteBulkRequest, + AdminEmojiDeleteBulkErrors, AdminEmojiDeleteRequest, + AdminEmojiDeleteErrors, AdminEmojiImportZipRequest, + AdminEmojiImportZipErrors, AdminEmojiListRemoteRequest, AdminEmojiListRemoteResponse, + AdminEmojiListRemoteErrors, AdminEmojiListRequest, AdminEmojiListResponse, + AdminEmojiListErrors, AdminEmojiRemoveAliasesBulkRequest, + AdminEmojiRemoveAliasesBulkErrors, AdminEmojiSetAliasesBulkRequest, + AdminEmojiSetAliasesBulkErrors, AdminEmojiSetCategoryBulkRequest, + AdminEmojiSetCategoryBulkErrors, AdminEmojiSetLicenseBulkRequest, + AdminEmojiSetLicenseBulkErrors, AdminEmojiUpdateRequest, + AdminEmojiUpdateErrors, AdminFederationDeleteAllFilesRequest, + AdminFederationDeleteAllFilesErrors, AdminFederationRefreshRemoteInstanceMetadataRequest, + AdminFederationRefreshRemoteInstanceMetadataErrors, AdminFederationRemoveAllFollowingRequest, + AdminFederationRemoveAllFollowingErrors, AdminFederationUpdateInstanceRequest, + AdminFederationUpdateInstanceErrors, AdminGetIndexStatsResponse, + AdminGetIndexStatsErrors, AdminGetTableStatsResponse, + AdminGetTableStatsErrors, AdminGetUserIpsRequest, AdminGetUserIpsResponse, + AdminGetUserIpsErrors, AdminInviteCreateRequest, AdminInviteCreateResponse, + AdminInviteCreateErrors, AdminInviteListRequest, AdminInviteListResponse, + AdminInviteListErrors, AdminPromoCreateRequest, + AdminPromoCreateErrors, + AdminQueueClearErrors, AdminQueueDeliverDelayedResponse, + AdminQueueDeliverDelayedErrors, AdminQueueInboxDelayedResponse, + AdminQueueInboxDelayedErrors, AdminQueuePromoteRequest, + AdminQueuePromoteErrors, AdminQueueStatsResponse, + AdminQueueStatsErrors, AdminRelaysAddRequest, AdminRelaysAddResponse, + AdminRelaysAddErrors, AdminRelaysListResponse, + AdminRelaysListErrors, AdminRelaysRemoveRequest, + AdminRelaysRemoveErrors, AdminResetPasswordRequest, AdminResetPasswordResponse, + AdminResetPasswordErrors, AdminResolveAbuseUserReportRequest, + AdminResolveAbuseUserReportErrors, AdminSendEmailRequest, + AdminSendEmailErrors, AdminServerInfoResponse, + AdminServerInfoErrors, AdminShowModerationLogsRequest, AdminShowModerationLogsResponse, + AdminShowModerationLogsErrors, AdminShowUserRequest, AdminShowUserResponse, + AdminShowUserErrors, AdminShowUsersRequest, AdminShowUsersResponse, + AdminShowUsersErrors, AdminSuspendUserRequest, + AdminSuspendUserErrors, AdminUnsuspendUserRequest, + AdminUnsuspendUserErrors, AdminUpdateMetaRequest, + AdminUpdateMetaErrors, AdminDeleteAccountRequest, + AdminDeleteAccountErrors, AdminUpdateUserNoteRequest, + AdminUpdateUserNoteErrors, AdminRolesCreateRequest, AdminRolesCreateResponse, + AdminRolesCreateErrors, AdminRolesDeleteRequest, + AdminRolesDeleteErrors, AdminRolesListResponse, + AdminRolesListErrors, AdminRolesShowRequest, AdminRolesShowResponse, + AdminRolesShowErrors, AdminRolesUpdateRequest, + AdminRolesUpdateErrors, AdminRolesAssignRequest, + AdminRolesAssignErrors, AdminRolesUnassignRequest, + AdminRolesUnassignErrors, AdminRolesUpdateDefaultPoliciesRequest, + AdminRolesUpdateDefaultPoliciesErrors, AdminRolesUsersRequest, AdminRolesUsersResponse, + AdminRolesUsersErrors, AdminSystemWebhookCreateRequest, AdminSystemWebhookCreateResponse, + AdminSystemWebhookCreateErrors, AdminSystemWebhookDeleteRequest, + AdminSystemWebhookDeleteErrors, AdminSystemWebhookListRequest, AdminSystemWebhookListResponse, + AdminSystemWebhookListErrors, AdminSystemWebhookShowRequest, AdminSystemWebhookShowResponse, + AdminSystemWebhookShowErrors, AdminSystemWebhookUpdateRequest, AdminSystemWebhookUpdateResponse, + AdminSystemWebhookUpdateErrors, AnnouncementsRequest, AnnouncementsResponse, + AnnouncementsErrors, AnnouncementsShowRequest, AnnouncementsShowResponse, + AnnouncementsShowErrors, AntennasCreateRequest, AntennasCreateResponse, + AntennasCreateErrors, AntennasDeleteRequest, + AntennasDeleteErrors, AntennasListResponse, + AntennasListErrors, AntennasNotesRequest, AntennasNotesResponse, + AntennasNotesErrors, AntennasShowRequest, AntennasShowResponse, + AntennasShowErrors, AntennasUpdateRequest, AntennasUpdateResponse, + AntennasUpdateErrors, ApGetRequest, ApGetResponse, + ApGetErrors, ApShowRequest, ApShowResponse, + ApShowErrors, AppCreateRequest, AppCreateResponse, + AppCreateErrors, AppShowRequest, AppShowResponse, + AppShowErrors, AuthAcceptRequest, + AuthAcceptErrors, AuthSessionGenerateRequest, AuthSessionGenerateResponse, + AuthSessionGenerateErrors, AuthSessionShowRequest, AuthSessionShowResponse, + AuthSessionShowErrors, AuthSessionUserkeyRequest, AuthSessionUserkeyResponse, + AuthSessionUserkeyErrors, BlockingCreateRequest, BlockingCreateResponse, + BlockingCreateErrors, BlockingDeleteRequest, BlockingDeleteResponse, + BlockingDeleteErrors, BlockingListRequest, BlockingListResponse, + BlockingListErrors, ChannelsCreateRequest, ChannelsCreateResponse, + ChannelsCreateErrors, ChannelsFeaturedResponse, + ChannelsFeaturedErrors, ChannelsFollowRequest, + ChannelsFollowErrors, ChannelsFollowedRequest, ChannelsFollowedResponse, + ChannelsFollowedErrors, ChannelsOwnedRequest, ChannelsOwnedResponse, + ChannelsOwnedErrors, ChannelsShowRequest, ChannelsShowResponse, + ChannelsShowErrors, ChannelsTimelineRequest, ChannelsTimelineResponse, + ChannelsTimelineErrors, ChannelsUnfollowRequest, + ChannelsUnfollowErrors, ChannelsUpdateRequest, ChannelsUpdateResponse, + ChannelsUpdateErrors, ChannelsFavoriteRequest, + ChannelsFavoriteErrors, ChannelsUnfavoriteRequest, + ChannelsUnfavoriteErrors, ChannelsMyFavoritesResponse, + ChannelsMyFavoritesErrors, ChannelsSearchRequest, ChannelsSearchResponse, + ChannelsSearchErrors, ChartsActiveUsersRequest, ChartsActiveUsersResponse, + ChartsActiveUsersErrors, ChartsApRequestRequest, ChartsApRequestResponse, + ChartsApRequestErrors, ChartsDriveRequest, ChartsDriveResponse, + ChartsDriveErrors, ChartsFederationRequest, ChartsFederationResponse, + ChartsFederationErrors, ChartsInstanceRequest, ChartsInstanceResponse, + ChartsInstanceErrors, ChartsNotesRequest, ChartsNotesResponse, + ChartsNotesErrors, ChartsUserDriveRequest, ChartsUserDriveResponse, + ChartsUserDriveErrors, ChartsUserFollowingRequest, ChartsUserFollowingResponse, + ChartsUserFollowingErrors, ChartsUserNotesRequest, ChartsUserNotesResponse, + ChartsUserNotesErrors, ChartsUserPvRequest, ChartsUserPvResponse, + ChartsUserPvErrors, ChartsUserReactionsRequest, ChartsUserReactionsResponse, + ChartsUserReactionsErrors, ChartsUsersRequest, ChartsUsersResponse, + ChartsUsersErrors, ClipsAddNoteRequest, + ClipsAddNoteErrors, ClipsRemoveNoteRequest, + ClipsRemoveNoteErrors, ClipsCreateRequest, ClipsCreateResponse, + ClipsCreateErrors, ClipsDeleteRequest, + ClipsDeleteErrors, ClipsListResponse, + ClipsListErrors, ClipsNotesRequest, ClipsNotesResponse, + ClipsNotesErrors, ClipsShowRequest, ClipsShowResponse, + ClipsShowErrors, ClipsUpdateRequest, ClipsUpdateResponse, + ClipsUpdateErrors, ClipsFavoriteRequest, + ClipsFavoriteErrors, ClipsUnfavoriteRequest, + ClipsUnfavoriteErrors, ClipsMyFavoritesResponse, + ClipsMyFavoritesErrors, DriveResponse, + DriveErrors, DriveFilesRequest, DriveFilesResponse, + DriveFilesErrors, DriveFilesAttachedNotesRequest, DriveFilesAttachedNotesResponse, + DriveFilesAttachedNotesErrors, DriveFilesCheckExistenceRequest, DriveFilesCheckExistenceResponse, + DriveFilesCheckExistenceErrors, DriveFilesCreateRequest, DriveFilesCreateResponse, + DriveFilesCreateErrors, DriveFilesDeleteRequest, + DriveFilesDeleteErrors, DriveFilesFindByHashRequest, DriveFilesFindByHashResponse, + DriveFilesFindByHashErrors, DriveFilesFindRequest, DriveFilesFindResponse, + DriveFilesFindErrors, DriveFilesShowRequest, DriveFilesShowResponse, + DriveFilesShowErrors, DriveFilesUpdateRequest, DriveFilesUpdateResponse, + DriveFilesUpdateErrors, DriveFilesUploadFromUrlRequest, + DriveFilesUploadFromUrlErrors, DriveFoldersRequest, DriveFoldersResponse, + DriveFoldersErrors, DriveFoldersCreateRequest, DriveFoldersCreateResponse, + DriveFoldersCreateErrors, DriveFoldersDeleteRequest, + DriveFoldersDeleteErrors, DriveFoldersFindRequest, DriveFoldersFindResponse, + DriveFoldersFindErrors, DriveFoldersShowRequest, DriveFoldersShowResponse, + DriveFoldersShowErrors, DriveFoldersUpdateRequest, DriveFoldersUpdateResponse, + DriveFoldersUpdateErrors, DriveStreamRequest, DriveStreamResponse, + DriveStreamErrors, EmailAddressAvailableRequest, EmailAddressAvailableResponse, + EmailAddressAvailableErrors, EndpointRequest, EndpointResponse, + EndpointErrors, EndpointsResponse, + EndpointsErrors_2 as EndpointsErrors, + ExportCustomEmojisErrors, FederationFollowersRequest, FederationFollowersResponse, + FederationFollowersErrors, FederationFollowingRequest, FederationFollowingResponse, + FederationFollowingErrors, FederationInstancesRequest, FederationInstancesResponse, + FederationInstancesErrors, FederationShowInstanceRequest, FederationShowInstanceResponse, + FederationShowInstanceErrors, FederationUpdateRemoteUserRequest, + FederationUpdateRemoteUserErrors, FederationUsersRequest, FederationUsersResponse, + FederationUsersErrors, FederationStatsRequest, FederationStatsResponse, + FederationStatsErrors, FollowingCreateRequest, FollowingCreateResponse, + FollowingCreateErrors, FollowingDeleteRequest, FollowingDeleteResponse, + FollowingDeleteErrors, FollowingUpdateRequest, FollowingUpdateResponse, + FollowingUpdateErrors, FollowingUpdateAllRequest, + FollowingUpdateAllErrors, FollowingInvalidateRequest, FollowingInvalidateResponse, + FollowingInvalidateErrors, FollowingRequestsAcceptRequest, + FollowingRequestsAcceptErrors, FollowingRequestsCancelRequest, FollowingRequestsCancelResponse, + FollowingRequestsCancelErrors, FollowingRequestsListRequest, FollowingRequestsListResponse, + FollowingRequestsListErrors, FollowingRequestsRejectRequest, + FollowingRequestsRejectErrors, GalleryFeaturedRequest, GalleryFeaturedResponse, + GalleryFeaturedErrors, GalleryPopularResponse, + GalleryPopularErrors, GalleryPostsRequest, GalleryPostsResponse, + GalleryPostsErrors, GalleryPostsCreateRequest, GalleryPostsCreateResponse, + GalleryPostsCreateErrors, GalleryPostsDeleteRequest, + GalleryPostsDeleteErrors, GalleryPostsLikeRequest, + GalleryPostsLikeErrors, GalleryPostsShowRequest, GalleryPostsShowResponse, + GalleryPostsShowErrors, GalleryPostsUnlikeRequest, + GalleryPostsUnlikeErrors, GalleryPostsUpdateRequest, GalleryPostsUpdateResponse, + GalleryPostsUpdateErrors, GetOnlineUsersCountResponse, + GetOnlineUsersCountErrors, GetAvatarDecorationsResponse, + GetAvatarDecorationsErrors, HashtagsListRequest, HashtagsListResponse, + HashtagsListErrors, HashtagsSearchRequest, HashtagsSearchResponse, + HashtagsSearchErrors, HashtagsShowRequest, HashtagsShowResponse, + HashtagsShowErrors, HashtagsTrendResponse, + HashtagsTrendErrors, HashtagsUsersRequest, HashtagsUsersResponse, + HashtagsUsersErrors, IResponse, + IErrors, I2faDoneRequest, I2faDoneResponse, + I2faDoneErrors, I2faKeyDoneRequest, I2faKeyDoneResponse, + I2faKeyDoneErrors, I2faPasswordLessRequest, + I2faPasswordLessErrors, I2faRegisterKeyRequest, I2faRegisterKeyResponse, + I2faRegisterKeyErrors, I2faRegisterRequest, I2faRegisterResponse, + I2faRegisterErrors, I2faUpdateKeyRequest, + I2faUpdateKeyErrors, I2faRemoveKeyRequest, + I2faRemoveKeyErrors, I2faUnregisterRequest, + I2faUnregisterErrors, IAppsRequest, IAppsResponse, + IAppsErrors, IAuthorizedAppsRequest, IAuthorizedAppsResponse, + IAuthorizedAppsErrors, IClaimAchievementRequest, + IClaimAchievementErrors, IChangePasswordRequest, + IChangePasswordErrors, IDeleteAccountRequest, + IDeleteAccountErrors, + IExportBlockingErrors, IExportFollowingRequest, + IExportFollowingErrors, + IExportMuteErrors, + IExportNotesErrors, + IExportClipsErrors, + IExportFavoritesErrors, + IExportUserListsErrors, + IExportAntennasErrors, IFavoritesRequest, IFavoritesResponse, + IFavoritesErrors, IGalleryLikesRequest, IGalleryLikesResponse, + IGalleryLikesErrors, IGalleryPostsRequest, IGalleryPostsResponse, + IGalleryPostsErrors, IImportBlockingRequest, + IImportBlockingErrors, IImportFollowingRequest, + IImportFollowingErrors, IImportMutingRequest, + IImportMutingErrors, IImportUserListsRequest, + IImportUserListsErrors, IImportAntennasRequest, + IImportAntennasErrors, INotificationsRequest, INotificationsResponse, + INotificationsErrors, INotificationsGroupedRequest, INotificationsGroupedResponse, + INotificationsGroupedErrors, IPageLikesRequest, IPageLikesResponse, + IPageLikesErrors, IPagesRequest, IPagesResponse, + IPagesErrors, IPinRequest, IPinResponse, + IPinErrors, + IReadAllUnreadNotesErrors, IReadAnnouncementRequest, + IReadAnnouncementErrors, IRegenerateTokenRequest, + IRegenerateTokenErrors, IRegistryGetAllRequest, IRegistryGetAllResponse, + IRegistryGetAllErrors, IRegistryGetDetailRequest, IRegistryGetDetailResponse, + IRegistryGetDetailErrors, IRegistryGetRequest, IRegistryGetResponse, + IRegistryGetErrors, IRegistryKeysWithTypeRequest, IRegistryKeysWithTypeResponse, + IRegistryKeysWithTypeErrors, IRegistryKeysRequest, IRegistryKeysResponse, + IRegistryKeysErrors, IRegistryRemoveRequest, + IRegistryRemoveErrors, IRegistryScopesWithDomainResponse, + IRegistryScopesWithDomainErrors, IRegistrySetRequest, + IRegistrySetErrors, IRevokeTokenRequest, + IRevokeTokenErrors, ISigninHistoryRequest, ISigninHistoryResponse, + ISigninHistoryErrors, IUnpinRequest, IUnpinResponse, + IUnpinErrors, IUpdateEmailRequest, IUpdateEmailResponse, + IUpdateEmailErrors, IUpdateRequest, IUpdateResponse, + IUpdateErrors, IMoveRequest, IMoveResponse, + IMoveErrors, IWebhooksCreateRequest, IWebhooksCreateResponse, + IWebhooksCreateErrors, IWebhooksListResponse, + IWebhooksListErrors, IWebhooksShowRequest, IWebhooksShowResponse, + IWebhooksShowErrors, IWebhooksUpdateRequest, + IWebhooksUpdateErrors, IWebhooksDeleteRequest, + IWebhooksDeleteErrors, InviteCreateResponse, + InviteCreateErrors, InviteDeleteRequest, + InviteDeleteErrors, InviteListRequest, InviteListResponse, + InviteListErrors, InviteLimitResponse, + InviteLimitErrors, MetaRequest, MetaResponse, + MetaErrors, EmojisResponse, + EmojisErrors, EmojiRequest, EmojiResponse, + EmojiErrors, MiauthGenTokenRequest, MiauthGenTokenResponse, + MiauthGenTokenErrors, MuteCreateRequest, + MuteCreateErrors, MuteDeleteRequest, + MuteDeleteErrors, MuteListRequest, MuteListResponse, + MuteListErrors, RenoteMuteCreateRequest, + RenoteMuteCreateErrors, RenoteMuteDeleteRequest, + RenoteMuteDeleteErrors, RenoteMuteListRequest, RenoteMuteListResponse, + RenoteMuteListErrors, MyAppsRequest, MyAppsResponse, + MyAppsErrors, NotesRequest, NotesResponse, + NotesErrors, NotesChildrenRequest, NotesChildrenResponse, + NotesChildrenErrors, NotesClipsRequest, NotesClipsResponse, + NotesClipsErrors, NotesConversationRequest, NotesConversationResponse, + NotesConversationErrors, NotesCreateRequest, NotesCreateResponse, + NotesCreateErrors, NotesDeleteRequest, + NotesDeleteErrors, NotesFavoritesCreateRequest, + NotesFavoritesCreateErrors, NotesFavoritesDeleteRequest, + NotesFavoritesDeleteErrors, NotesFeaturedRequest, NotesFeaturedResponse, + NotesFeaturedErrors, NotesGlobalTimelineRequest, NotesGlobalTimelineResponse, + NotesGlobalTimelineErrors, NotesHybridTimelineRequest, NotesHybridTimelineResponse, + NotesHybridTimelineErrors, NotesLocalTimelineRequest, NotesLocalTimelineResponse, + NotesLocalTimelineErrors, NotesMentionsRequest, NotesMentionsResponse, + NotesMentionsErrors, NotesPollsRecommendationRequest, NotesPollsRecommendationResponse, + NotesPollsRecommendationErrors, NotesPollsVoteRequest, + NotesPollsVoteErrors, NotesReactionsRequest, NotesReactionsResponse, + NotesReactionsErrors, NotesReactionsCreateRequest, + NotesReactionsCreateErrors, NotesReactionsDeleteRequest, + NotesReactionsDeleteErrors, NotesRenotesRequest, NotesRenotesResponse, + NotesRenotesErrors, NotesRepliesRequest, NotesRepliesResponse, + NotesRepliesErrors, NotesSearchByTagRequest, NotesSearchByTagResponse, + NotesSearchByTagErrors, NotesSearchRequest, NotesSearchResponse, + NotesSearchErrors, NotesShowRequest, NotesShowResponse, + NotesShowErrors, NotesStateRequest, NotesStateResponse, + NotesStateErrors, NotesThreadMutingCreateRequest, + NotesThreadMutingCreateErrors, NotesThreadMutingDeleteRequest, + NotesThreadMutingDeleteErrors, NotesTimelineRequest, NotesTimelineResponse, + NotesTimelineErrors, NotesTranslateRequest, NotesTranslateResponse, + NotesTranslateErrors, NotesUnrenoteRequest, + NotesUnrenoteErrors, NotesUserListTimelineRequest, NotesUserListTimelineResponse, + NotesUserListTimelineErrors, NotificationsCreateRequest, + NotificationsCreateErrors, + NotificationsFlushErrors, + NotificationsMarkAllAsReadErrors, + NotificationsTestNotificationErrors, PagePushRequest, + PagePushErrors, PagesCreateRequest, PagesCreateResponse, + PagesCreateErrors, PagesDeleteRequest, + PagesDeleteErrors, PagesFeaturedResponse, + PagesFeaturedErrors, PagesLikeRequest, + PagesLikeErrors, PagesShowRequest, PagesShowResponse, + PagesShowErrors, PagesUnlikeRequest, + PagesUnlikeErrors, PagesUpdateRequest, + PagesUpdateErrors, FlashCreateRequest, FlashCreateResponse, + FlashCreateErrors, FlashDeleteRequest, + FlashDeleteErrors, FlashFeaturedResponse, + FlashFeaturedErrors, FlashLikeRequest, + FlashLikeErrors, FlashShowRequest, FlashShowResponse, + FlashShowErrors, FlashUnlikeRequest, + FlashUnlikeErrors, FlashUpdateRequest, + FlashUpdateErrors, FlashMyRequest, FlashMyResponse, + FlashMyErrors, FlashMyLikesRequest, FlashMyLikesResponse, + FlashMyLikesErrors, PingResponse, + PingErrors, PinnedUsersResponse, + PinnedUsersErrors, PromoReadRequest, + PromoReadErrors, RolesListResponse, + RolesListErrors, RolesShowRequest, RolesShowResponse, + RolesShowErrors, RolesUsersRequest, RolesUsersResponse, + RolesUsersErrors, RolesNotesRequest, RolesNotesResponse, + RolesNotesErrors, RequestResetPasswordRequest, + RequestResetPasswordErrors, + ResetDbErrors, ResetPasswordRequest, + ResetPasswordErrors, ServerInfoResponse, + ServerInfoErrors, StatsResponse, + StatsErrors, SwShowRegistrationRequest, SwShowRegistrationResponse, + SwShowRegistrationErrors, SwUpdateRegistrationRequest, SwUpdateRegistrationResponse, + SwUpdateRegistrationErrors, SwRegisterRequest, SwRegisterResponse, + SwRegisterErrors, SwUnregisterRequest, + SwUnregisterErrors, TestRequest, TestResponse, + TestErrors, UsernameAvailableRequest, UsernameAvailableResponse, + UsernameAvailableErrors, UsersRequest, UsersResponse, + UsersErrors, UsersClipsRequest, UsersClipsResponse, + UsersClipsErrors, UsersFollowersRequest, UsersFollowersResponse, + UsersFollowersErrors, UsersFollowingRequest, UsersFollowingResponse, + UsersFollowingErrors, UsersGalleryPostsRequest, UsersGalleryPostsResponse, + UsersGalleryPostsErrors, UsersGetFrequentlyRepliedUsersRequest, UsersGetFrequentlyRepliedUsersResponse, + UsersGetFrequentlyRepliedUsersErrors, UsersFeaturedNotesRequest, UsersFeaturedNotesResponse, + UsersFeaturedNotesErrors, UsersListsCreateRequest, UsersListsCreateResponse, + UsersListsCreateErrors, UsersListsDeleteRequest, + UsersListsDeleteErrors, UsersListsListRequest, UsersListsListResponse, + UsersListsListErrors, UsersListsPullRequest, + UsersListsPullErrors, UsersListsPushRequest, + UsersListsPushErrors, UsersListsShowRequest, UsersListsShowResponse, + UsersListsShowErrors, UsersListsFavoriteRequest, + UsersListsFavoriteErrors, UsersListsUnfavoriteRequest, + UsersListsUnfavoriteErrors, UsersListsUpdateRequest, UsersListsUpdateResponse, + UsersListsUpdateErrors, UsersListsCreateFromPublicRequest, UsersListsCreateFromPublicResponse, + UsersListsCreateFromPublicErrors, UsersListsUpdateMembershipRequest, + UsersListsUpdateMembershipErrors, UsersListsGetMembershipsRequest, UsersListsGetMembershipsResponse, + UsersListsGetMembershipsErrors, UsersNotesRequest, UsersNotesResponse, + UsersNotesErrors, UsersPagesRequest, UsersPagesResponse, + UsersPagesErrors, UsersFlashsRequest, UsersFlashsResponse, + UsersFlashsErrors, UsersReactionsRequest, UsersReactionsResponse, + UsersReactionsErrors, UsersRecommendationRequest, UsersRecommendationResponse, + UsersRecommendationErrors, UsersRelationRequest, UsersRelationResponse, + UsersRelationErrors, UsersReportAbuseRequest, + UsersReportAbuseErrors, UsersSearchByUsernameAndHostRequest, UsersSearchByUsernameAndHostResponse, + UsersSearchByUsernameAndHostErrors, UsersSearchRequest, UsersSearchResponse, + UsersSearchErrors, UsersShowRequest, UsersShowResponse, + UsersShowErrors, UsersAchievementsRequest, UsersAchievementsResponse, + UsersAchievementsErrors, UsersUpdateMemoRequest, + UsersUpdateMemoErrors, FetchRssRequest, FetchRssResponse, + FetchRssErrors, FetchExternalResourcesRequest, FetchExternalResourcesResponse, + FetchExternalResourcesErrors, RetentionResponse, + RetentionErrors, BubbleGameRegisterRequest, + BubbleGameRegisterErrors, BubbleGameRankingRequest, BubbleGameRankingResponse, + BubbleGameRankingErrors, ReversiCancelMatchRequest, + ReversiCancelMatchErrors, ReversiGamesRequest, ReversiGamesResponse, + ReversiGamesErrors, ReversiMatchRequest, ReversiMatchResponse, + ReversiMatchErrors, ReversiInvitationsResponse, + ReversiInvitationsErrors, ReversiShowGameRequest, ReversiShowGameResponse, + ReversiShowGameErrors, ReversiSurrenderRequest, + ReversiSurrenderErrors, ReversiVerifyRequest, ReversiVerifyResponse, + ReversiVerifyErrors, Error_2 as Error, UserLite, UserDetailedNotMeOnly, @@ -1818,12 +2707,21 @@ export { entities } // @public (undocumented) type Error_2 = components['schemas']['Error']; +// @public (undocumented) +type ExportCustomEmojisErrors = EndpointsErrors['export-custom-emojis'][keyof EndpointsErrors['export-custom-emojis']]; + +// @public (undocumented) +type FederationFollowersErrors = EndpointsErrors['federation___followers'][keyof EndpointsErrors['federation___followers']]; + // @public (undocumented) type FederationFollowersRequest = operations['federation___followers']['requestBody']['content']['application/json']; // @public (undocumented) type FederationFollowersResponse = operations['federation___followers']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FederationFollowingErrors = EndpointsErrors['federation___following'][keyof EndpointsErrors['federation___following']]; + // @public (undocumented) type FederationFollowingRequest = operations['federation___following']['requestBody']['content']['application/json']; @@ -1833,33 +2731,51 @@ type FederationFollowingResponse = operations['federation___following']['respons // @public (undocumented) type FederationInstance = components['schemas']['FederationInstance']; +// @public (undocumented) +type FederationInstancesErrors = EndpointsErrors['federation___instances'][keyof EndpointsErrors['federation___instances']]; + // @public (undocumented) type FederationInstancesRequest = operations['federation___instances']['requestBody']['content']['application/json']; // @public (undocumented) type FederationInstancesResponse = operations['federation___instances']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FederationShowInstanceErrors = EndpointsErrors['federation___show-instance'][keyof EndpointsErrors['federation___show-instance']]; + // @public (undocumented) type FederationShowInstanceRequest = operations['federation___show-instance']['requestBody']['content']['application/json']; // @public (undocumented) type FederationShowInstanceResponse = operations['federation___show-instance']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FederationStatsErrors = EndpointsErrors['federation___stats'][keyof EndpointsErrors['federation___stats']]; + // @public (undocumented) type FederationStatsRequest = operations['federation___stats']['requestBody']['content']['application/json']; // @public (undocumented) type FederationStatsResponse = operations['federation___stats']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FederationUpdateRemoteUserErrors = EndpointsErrors['federation___update-remote-user'][keyof EndpointsErrors['federation___update-remote-user']]; + // @public (undocumented) type FederationUpdateRemoteUserRequest = operations['federation___update-remote-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type FederationUsersErrors = EndpointsErrors['federation___users'][keyof EndpointsErrors['federation___users']]; + // @public (undocumented) type FederationUsersRequest = operations['federation___users']['requestBody']['content']['application/json']; // @public (undocumented) type FederationUsersResponse = operations['federation___users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FetchExternalResourcesErrors = EndpointsErrors['fetch-external-resources'][keyof EndpointsErrors['fetch-external-resources']]; + // @public (undocumented) type FetchExternalResourcesRequest = operations['fetch-external-resources']['requestBody']['content']['application/json']; @@ -1880,6 +2796,9 @@ type FetchLike = (input: string, init?: { json(): Promise; }>; +// @public (undocumented) +type FetchRssErrors = EndpointsErrors['fetch-rss'][keyof EndpointsErrors['fetch-rss']]; + // @public (undocumented) type FetchRssRequest = operations['fetch-rss']['requestBody']['content']['application/json']; @@ -1889,21 +2808,39 @@ type FetchRssResponse = operations['fetch-rss']['responses']['200']['content'][' // @public (undocumented) type Flash = components['schemas']['Flash']; +// @public (undocumented) +type FlashCreateErrors = EndpointsErrors['flash___create'][keyof EndpointsErrors['flash___create']]; + // @public (undocumented) type FlashCreateRequest = operations['flash___create']['requestBody']['content']['application/json']; // @public (undocumented) type FlashCreateResponse = operations['flash___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FlashDeleteErrors = EndpointsErrors['flash___delete'][keyof EndpointsErrors['flash___delete']]; + // @public (undocumented) type FlashDeleteRequest = operations['flash___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type FlashFeaturedErrors = EndpointsErrors['flash___featured'][keyof EndpointsErrors['flash___featured']]; + // @public (undocumented) type FlashFeaturedResponse = operations['flash___featured']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FlashLikeErrors = EndpointsErrors['flash___like'][keyof EndpointsErrors['flash___like']]; + // @public (undocumented) type FlashLikeRequest = operations['flash___like']['requestBody']['content']['application/json']; +// @public (undocumented) +type FlashMyErrors = EndpointsErrors['flash___my'][keyof EndpointsErrors['flash___my']]; + +// @public (undocumented) +type FlashMyLikesErrors = EndpointsErrors['flash___my-likes'][keyof EndpointsErrors['flash___my-likes']]; + // @public (undocumented) type FlashMyLikesRequest = operations['flash___my-likes']['requestBody']['content']['application/json']; @@ -1916,15 +2853,24 @@ type FlashMyRequest = operations['flash___my']['requestBody']['content']['applic // @public (undocumented) type FlashMyResponse = operations['flash___my']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FlashShowErrors = EndpointsErrors['flash___show'][keyof EndpointsErrors['flash___show']]; + // @public (undocumented) type FlashShowRequest = operations['flash___show']['requestBody']['content']['application/json']; // @public (undocumented) type FlashShowResponse = operations['flash___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FlashUnlikeErrors = EndpointsErrors['flash___unlike'][keyof EndpointsErrors['flash___unlike']]; + // @public (undocumented) type FlashUnlikeRequest = operations['flash___unlike']['requestBody']['content']['application/json']; +// @public (undocumented) +type FlashUpdateErrors = EndpointsErrors['flash___update'][keyof EndpointsErrors['flash___update']]; + // @public (undocumented) type FlashUpdateRequest = operations['flash___update']['requestBody']['content']['application/json']; @@ -1934,45 +2880,72 @@ export const followersVisibilities: readonly ["public", "followers", "private"]; // @public (undocumented) type Following = components['schemas']['Following']; +// @public (undocumented) +type FollowingCreateErrors = EndpointsErrors['following___create'][keyof EndpointsErrors['following___create']]; + // @public (undocumented) type FollowingCreateRequest = operations['following___create']['requestBody']['content']['application/json']; // @public (undocumented) type FollowingCreateResponse = operations['following___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FollowingDeleteErrors = EndpointsErrors['following___delete'][keyof EndpointsErrors['following___delete']]; + // @public (undocumented) type FollowingDeleteRequest = operations['following___delete']['requestBody']['content']['application/json']; // @public (undocumented) type FollowingDeleteResponse = operations['following___delete']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FollowingInvalidateErrors = EndpointsErrors['following___invalidate'][keyof EndpointsErrors['following___invalidate']]; + // @public (undocumented) type FollowingInvalidateRequest = operations['following___invalidate']['requestBody']['content']['application/json']; // @public (undocumented) type FollowingInvalidateResponse = operations['following___invalidate']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FollowingRequestsAcceptErrors = EndpointsErrors['following___requests___accept'][keyof EndpointsErrors['following___requests___accept']]; + // @public (undocumented) type FollowingRequestsAcceptRequest = operations['following___requests___accept']['requestBody']['content']['application/json']; +// @public (undocumented) +type FollowingRequestsCancelErrors = EndpointsErrors['following___requests___cancel'][keyof EndpointsErrors['following___requests___cancel']]; + // @public (undocumented) type FollowingRequestsCancelRequest = operations['following___requests___cancel']['requestBody']['content']['application/json']; // @public (undocumented) type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FollowingRequestsListErrors = EndpointsErrors['following___requests___list'][keyof EndpointsErrors['following___requests___list']]; + // @public (undocumented) type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json']; // @public (undocumented) type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type FollowingRequestsRejectErrors = EndpointsErrors['following___requests___reject'][keyof EndpointsErrors['following___requests___reject']]; + // @public (undocumented) type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json']; +// @public (undocumented) +type FollowingUpdateAllErrors = EndpointsErrors['following___update-all'][keyof EndpointsErrors['following___update-all']]; + // @public (undocumented) type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json']; +// @public (undocumented) +type FollowingUpdateErrors = EndpointsErrors['following___update'][keyof EndpointsErrors['following___update']]; + // @public (undocumented) type FollowingUpdateRequest = operations['following___update']['requestBody']['content']['application/json']; @@ -1982,27 +2955,45 @@ type FollowingUpdateResponse = operations['following___update']['responses']['20 // @public (undocumented) export const followingVisibilities: readonly ["public", "followers", "private"]; +// @public (undocumented) +type GalleryFeaturedErrors = EndpointsErrors['gallery___featured'][keyof EndpointsErrors['gallery___featured']]; + // @public (undocumented) type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json']; // @public (undocumented) type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GalleryPopularErrors = EndpointsErrors['gallery___popular'][keyof EndpointsErrors['gallery___popular']]; + // @public (undocumented) type GalleryPopularResponse = operations['gallery___popular']['responses']['200']['content']['application/json']; // @public (undocumented) type GalleryPost = components['schemas']['GalleryPost']; +// @public (undocumented) +type GalleryPostsCreateErrors = EndpointsErrors['gallery___posts___create'][keyof EndpointsErrors['gallery___posts___create']]; + // @public (undocumented) type GalleryPostsCreateRequest = operations['gallery___posts___create']['requestBody']['content']['application/json']; // @public (undocumented) type GalleryPostsCreateResponse = operations['gallery___posts___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GalleryPostsDeleteErrors = EndpointsErrors['gallery___posts___delete'][keyof EndpointsErrors['gallery___posts___delete']]; + // @public (undocumented) type GalleryPostsDeleteRequest = operations['gallery___posts___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type GalleryPostsErrors = EndpointsErrors['gallery___posts'][keyof EndpointsErrors['gallery___posts']]; + +// @public (undocumented) +type GalleryPostsLikeErrors = EndpointsErrors['gallery___posts___like'][keyof EndpointsErrors['gallery___posts___like']]; + // @public (undocumented) type GalleryPostsLikeRequest = operations['gallery___posts___like']['requestBody']['content']['application/json']; @@ -2012,72 +3003,117 @@ type GalleryPostsRequest = operations['gallery___posts']['requestBody']['content // @public (undocumented) type GalleryPostsResponse = operations['gallery___posts']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GalleryPostsShowErrors = EndpointsErrors['gallery___posts___show'][keyof EndpointsErrors['gallery___posts___show']]; + // @public (undocumented) type GalleryPostsShowRequest = operations['gallery___posts___show']['requestBody']['content']['application/json']; // @public (undocumented) type GalleryPostsShowResponse = operations['gallery___posts___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GalleryPostsUnlikeErrors = EndpointsErrors['gallery___posts___unlike'][keyof EndpointsErrors['gallery___posts___unlike']]; + // @public (undocumented) type GalleryPostsUnlikeRequest = operations['gallery___posts___unlike']['requestBody']['content']['application/json']; +// @public (undocumented) +type GalleryPostsUpdateErrors = EndpointsErrors['gallery___posts___update'][keyof EndpointsErrors['gallery___posts___update']]; + // @public (undocumented) type GalleryPostsUpdateRequest = operations['gallery___posts___update']['requestBody']['content']['application/json']; // @public (undocumented) type GalleryPostsUpdateResponse = operations['gallery___posts___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GetAvatarDecorationsErrors = EndpointsErrors['get-avatar-decorations'][keyof EndpointsErrors['get-avatar-decorations']]; + // @public (undocumented) type GetAvatarDecorationsResponse = operations['get-avatar-decorations']['responses']['200']['content']['application/json']; +// @public (undocumented) +type GetOnlineUsersCountErrors = EndpointsErrors['get-online-users-count'][keyof EndpointsErrors['get-online-users-count']]; + // @public (undocumented) type GetOnlineUsersCountResponse = operations['get-online-users-count']['responses']['200']['content']['application/json']; // @public (undocumented) type Hashtag = components['schemas']['Hashtag']; +// @public (undocumented) +type HashtagsListErrors = EndpointsErrors['hashtags___list'][keyof EndpointsErrors['hashtags___list']]; + // @public (undocumented) type HashtagsListRequest = operations['hashtags___list']['requestBody']['content']['application/json']; // @public (undocumented) type HashtagsListResponse = operations['hashtags___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type HashtagsSearchErrors = EndpointsErrors['hashtags___search'][keyof EndpointsErrors['hashtags___search']]; + // @public (undocumented) type HashtagsSearchRequest = operations['hashtags___search']['requestBody']['content']['application/json']; // @public (undocumented) type HashtagsSearchResponse = operations['hashtags___search']['responses']['200']['content']['application/json']; +// @public (undocumented) +type HashtagsShowErrors = EndpointsErrors['hashtags___show'][keyof EndpointsErrors['hashtags___show']]; + // @public (undocumented) type HashtagsShowRequest = operations['hashtags___show']['requestBody']['content']['application/json']; // @public (undocumented) type HashtagsShowResponse = operations['hashtags___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type HashtagsTrendErrors = EndpointsErrors['hashtags___trend'][keyof EndpointsErrors['hashtags___trend']]; + // @public (undocumented) type HashtagsTrendResponse = operations['hashtags___trend']['responses']['200']['content']['application/json']; +// @public (undocumented) +type HashtagsUsersErrors = EndpointsErrors['hashtags___users'][keyof EndpointsErrors['hashtags___users']]; + // @public (undocumented) type HashtagsUsersRequest = operations['hashtags___users']['requestBody']['content']['application/json']; // @public (undocumented) type HashtagsUsersResponse = operations['hashtags___users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type I2faDoneErrors = EndpointsErrors['i___2fa___done'][keyof EndpointsErrors['i___2fa___done']]; + // @public (undocumented) type I2faDoneRequest = operations['i___2fa___done']['requestBody']['content']['application/json']; // @public (undocumented) type I2faDoneResponse = operations['i___2fa___done']['responses']['200']['content']['application/json']; +// @public (undocumented) +type I2faKeyDoneErrors = EndpointsErrors['i___2fa___key-done'][keyof EndpointsErrors['i___2fa___key-done']]; + // @public (undocumented) type I2faKeyDoneRequest = operations['i___2fa___key-done']['requestBody']['content']['application/json']; // @public (undocumented) type I2faKeyDoneResponse = operations['i___2fa___key-done']['responses']['200']['content']['application/json']; +// @public (undocumented) +type I2faPasswordLessErrors = EndpointsErrors['i___2fa___password-less'][keyof EndpointsErrors['i___2fa___password-less']]; + // @public (undocumented) type I2faPasswordLessRequest = operations['i___2fa___password-less']['requestBody']['content']['application/json']; +// @public (undocumented) +type I2faRegisterErrors = EndpointsErrors['i___2fa___register'][keyof EndpointsErrors['i___2fa___register']]; + +// @public (undocumented) +type I2faRegisterKeyErrors = EndpointsErrors['i___2fa___register-key'][keyof EndpointsErrors['i___2fa___register-key']]; + // @public (undocumented) type I2faRegisterKeyRequest = operations['i___2fa___register-key']['requestBody']['content']['application/json']; @@ -2090,81 +3126,165 @@ type I2faRegisterRequest = operations['i___2fa___register']['requestBody']['cont // @public (undocumented) type I2faRegisterResponse = operations['i___2fa___register']['responses']['200']['content']['application/json']; +// @public (undocumented) +type I2faRemoveKeyErrors = EndpointsErrors['i___2fa___remove-key'][keyof EndpointsErrors['i___2fa___remove-key']]; + // @public (undocumented) type I2faRemoveKeyRequest = operations['i___2fa___remove-key']['requestBody']['content']['application/json']; +// @public (undocumented) +type I2faUnregisterErrors = EndpointsErrors['i___2fa___unregister'][keyof EndpointsErrors['i___2fa___unregister']]; + // @public (undocumented) type I2faUnregisterRequest = operations['i___2fa___unregister']['requestBody']['content']['application/json']; +// @public (undocumented) +type I2faUpdateKeyErrors = EndpointsErrors['i___2fa___update-key'][keyof EndpointsErrors['i___2fa___update-key']]; + // @public (undocumented) type I2faUpdateKeyRequest = operations['i___2fa___update-key']['requestBody']['content']['application/json']; +// @public (undocumented) +type IAppsErrors = EndpointsErrors['i___apps'][keyof EndpointsErrors['i___apps']]; + // @public (undocumented) type IAppsRequest = operations['i___apps']['requestBody']['content']['application/json']; // @public (undocumented) type IAppsResponse = operations['i___apps']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IAuthorizedAppsErrors = EndpointsErrors['i___authorized-apps'][keyof EndpointsErrors['i___authorized-apps']]; + // @public (undocumented) type IAuthorizedAppsRequest = operations['i___authorized-apps']['requestBody']['content']['application/json']; // @public (undocumented) type IAuthorizedAppsResponse = operations['i___authorized-apps']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IChangePasswordErrors = EndpointsErrors['i___change-password'][keyof EndpointsErrors['i___change-password']]; + // @public (undocumented) type IChangePasswordRequest = operations['i___change-password']['requestBody']['content']['application/json']; +// @public (undocumented) +type IClaimAchievementErrors = EndpointsErrors['i___claim-achievement'][keyof EndpointsErrors['i___claim-achievement']]; + // @public (undocumented) type IClaimAchievementRequest = operations['i___claim-achievement']['requestBody']['content']['application/json']; // @public (undocumented) type ID = string; +// @public (undocumented) +type IDeleteAccountErrors = EndpointsErrors['i___delete-account'][keyof EndpointsErrors['i___delete-account']]; + // @public (undocumented) type IDeleteAccountRequest = operations['i___delete-account']['requestBody']['content']['application/json']; +// @public (undocumented) +type IErrors = EndpointsErrors['i'][keyof EndpointsErrors['i']]; + +// @public (undocumented) +type IExportAntennasErrors = EndpointsErrors['i___export-antennas'][keyof EndpointsErrors['i___export-antennas']]; + +// @public (undocumented) +type IExportBlockingErrors = EndpointsErrors['i___export-blocking'][keyof EndpointsErrors['i___export-blocking']]; + +// @public (undocumented) +type IExportClipsErrors = EndpointsErrors['i___export-clips'][keyof EndpointsErrors['i___export-clips']]; + +// @public (undocumented) +type IExportFavoritesErrors = EndpointsErrors['i___export-favorites'][keyof EndpointsErrors['i___export-favorites']]; + +// @public (undocumented) +type IExportFollowingErrors = EndpointsErrors['i___export-following'][keyof EndpointsErrors['i___export-following']]; + // @public (undocumented) type IExportFollowingRequest = operations['i___export-following']['requestBody']['content']['application/json']; +// @public (undocumented) +type IExportMuteErrors = EndpointsErrors['i___export-mute'][keyof EndpointsErrors['i___export-mute']]; + +// @public (undocumented) +type IExportNotesErrors = EndpointsErrors['i___export-notes'][keyof EndpointsErrors['i___export-notes']]; + +// @public (undocumented) +type IExportUserListsErrors = EndpointsErrors['i___export-user-lists'][keyof EndpointsErrors['i___export-user-lists']]; + +// @public (undocumented) +type IFavoritesErrors = EndpointsErrors['i___favorites'][keyof EndpointsErrors['i___favorites']]; + // @public (undocumented) type IFavoritesRequest = operations['i___favorites']['requestBody']['content']['application/json']; // @public (undocumented) type IFavoritesResponse = operations['i___favorites']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IGalleryLikesErrors = EndpointsErrors['i___gallery___likes'][keyof EndpointsErrors['i___gallery___likes']]; + // @public (undocumented) type IGalleryLikesRequest = operations['i___gallery___likes']['requestBody']['content']['application/json']; // @public (undocumented) type IGalleryLikesResponse = operations['i___gallery___likes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IGalleryPostsErrors = EndpointsErrors['i___gallery___posts'][keyof EndpointsErrors['i___gallery___posts']]; + // @public (undocumented) type IGalleryPostsRequest = operations['i___gallery___posts']['requestBody']['content']['application/json']; // @public (undocumented) type IGalleryPostsResponse = operations['i___gallery___posts']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IImportAntennasErrors = EndpointsErrors['i___import-antennas'][keyof EndpointsErrors['i___import-antennas']]; + // @public (undocumented) type IImportAntennasRequest = operations['i___import-antennas']['requestBody']['content']['application/json']; +// @public (undocumented) +type IImportBlockingErrors = EndpointsErrors['i___import-blocking'][keyof EndpointsErrors['i___import-blocking']]; + // @public (undocumented) type IImportBlockingRequest = operations['i___import-blocking']['requestBody']['content']['application/json']; +// @public (undocumented) +type IImportFollowingErrors = EndpointsErrors['i___import-following'][keyof EndpointsErrors['i___import-following']]; + // @public (undocumented) type IImportFollowingRequest = operations['i___import-following']['requestBody']['content']['application/json']; +// @public (undocumented) +type IImportMutingErrors = EndpointsErrors['i___import-muting'][keyof EndpointsErrors['i___import-muting']]; + // @public (undocumented) type IImportMutingRequest = operations['i___import-muting']['requestBody']['content']['application/json']; +// @public (undocumented) +type IImportUserListsErrors = EndpointsErrors['i___import-user-lists'][keyof EndpointsErrors['i___import-user-lists']]; + // @public (undocumented) type IImportUserListsRequest = operations['i___import-user-lists']['requestBody']['content']['application/json']; +// @public (undocumented) +type IMoveErrors = EndpointsErrors['i___move'][keyof EndpointsErrors['i___move']]; + // @public (undocumented) type IMoveRequest = operations['i___move']['requestBody']['content']['application/json']; // @public (undocumented) type IMoveResponse = operations['i___move']['responses']['200']['content']['application/json']; +// @public (undocumented) +type INotificationsErrors = EndpointsErrors['i___notifications'][keyof EndpointsErrors['i___notifications']]; + +// @public (undocumented) +type INotificationsGroupedErrors = EndpointsErrors['i___notifications-grouped'][keyof EndpointsErrors['i___notifications-grouped']]; + // @public (undocumented) type INotificationsGroupedRequest = operations['i___notifications-grouped']['requestBody']['content']['application/json']; @@ -2180,135 +3300,219 @@ type INotificationsResponse = operations['i___notifications']['responses']['200' // @public (undocumented) type InviteCode = components['schemas']['InviteCode']; +// @public (undocumented) +type InviteCreateErrors = EndpointsErrors['invite___create'][keyof EndpointsErrors['invite___create']]; + // @public (undocumented) type InviteCreateResponse = operations['invite___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type InviteDeleteErrors = EndpointsErrors['invite___delete'][keyof EndpointsErrors['invite___delete']]; + // @public (undocumented) type InviteDeleteRequest = operations['invite___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type InviteLimitErrors = EndpointsErrors['invite___limit'][keyof EndpointsErrors['invite___limit']]; + // @public (undocumented) type InviteLimitResponse = operations['invite___limit']['responses']['200']['content']['application/json']; +// @public (undocumented) +type InviteListErrors = EndpointsErrors['invite___list'][keyof EndpointsErrors['invite___list']]; + // @public (undocumented) type InviteListRequest = operations['invite___list']['requestBody']['content']['application/json']; // @public (undocumented) type InviteListResponse = operations['invite___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IPageLikesErrors = EndpointsErrors['i___page-likes'][keyof EndpointsErrors['i___page-likes']]; + // @public (undocumented) type IPageLikesRequest = operations['i___page-likes']['requestBody']['content']['application/json']; // @public (undocumented) type IPageLikesResponse = operations['i___page-likes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IPagesErrors = EndpointsErrors['i___pages'][keyof EndpointsErrors['i___pages']]; + // @public (undocumented) type IPagesRequest = operations['i___pages']['requestBody']['content']['application/json']; // @public (undocumented) type IPagesResponse = operations['i___pages']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IPinErrors = EndpointsErrors['i___pin'][keyof EndpointsErrors['i___pin']]; + // @public (undocumented) type IPinRequest = operations['i___pin']['requestBody']['content']['application/json']; // @public (undocumented) type IPinResponse = operations['i___pin']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IReadAllUnreadNotesErrors = EndpointsErrors['i___read-all-unread-notes'][keyof EndpointsErrors['i___read-all-unread-notes']]; + +// @public (undocumented) +type IReadAnnouncementErrors = EndpointsErrors['i___read-announcement'][keyof EndpointsErrors['i___read-announcement']]; + // @public (undocumented) type IReadAnnouncementRequest = operations['i___read-announcement']['requestBody']['content']['application/json']; +// @public (undocumented) +type IRegenerateTokenErrors = EndpointsErrors['i___regenerate-token'][keyof EndpointsErrors['i___regenerate-token']]; + // @public (undocumented) type IRegenerateTokenRequest = operations['i___regenerate-token']['requestBody']['content']['application/json']; +// @public (undocumented) +type IRegistryGetAllErrors = EndpointsErrors['i___registry___get-all'][keyof EndpointsErrors['i___registry___get-all']]; + // @public (undocumented) type IRegistryGetAllRequest = operations['i___registry___get-all']['requestBody']['content']['application/json']; // @public (undocumented) type IRegistryGetAllResponse = operations['i___registry___get-all']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistryGetDetailErrors = EndpointsErrors['i___registry___get-detail'][keyof EndpointsErrors['i___registry___get-detail']]; + // @public (undocumented) type IRegistryGetDetailRequest = operations['i___registry___get-detail']['requestBody']['content']['application/json']; // @public (undocumented) type IRegistryGetDetailResponse = operations['i___registry___get-detail']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistryGetErrors = EndpointsErrors['i___registry___get'][keyof EndpointsErrors['i___registry___get']]; + // @public (undocumented) type IRegistryGetRequest = operations['i___registry___get']['requestBody']['content']['application/json']; // @public (undocumented) type IRegistryGetResponse = operations['i___registry___get']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistryKeysErrors = EndpointsErrors['i___registry___keys'][keyof EndpointsErrors['i___registry___keys']]; + // @public (undocumented) type IRegistryKeysRequest = operations['i___registry___keys']['requestBody']['content']['application/json']; // @public (undocumented) type IRegistryKeysResponse = operations['i___registry___keys']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistryKeysWithTypeErrors = EndpointsErrors['i___registry___keys-with-type'][keyof EndpointsErrors['i___registry___keys-with-type']]; + // @public (undocumented) type IRegistryKeysWithTypeRequest = operations['i___registry___keys-with-type']['requestBody']['content']['application/json']; // @public (undocumented) type IRegistryKeysWithTypeResponse = operations['i___registry___keys-with-type']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistryRemoveErrors = EndpointsErrors['i___registry___remove'][keyof EndpointsErrors['i___registry___remove']]; + // @public (undocumented) type IRegistryRemoveRequest = operations['i___registry___remove']['requestBody']['content']['application/json']; +// @public (undocumented) +type IRegistryScopesWithDomainErrors = EndpointsErrors['i___registry___scopes-with-domain'][keyof EndpointsErrors['i___registry___scopes-with-domain']]; + // @public (undocumented) type IRegistryScopesWithDomainResponse = operations['i___registry___scopes-with-domain']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRegistrySetErrors = EndpointsErrors['i___registry___set'][keyof EndpointsErrors['i___registry___set']]; + // @public (undocumented) type IRegistrySetRequest = operations['i___registry___set']['requestBody']['content']['application/json']; // @public (undocumented) type IResponse = operations['i']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IRevokeTokenErrors = EndpointsErrors['i___revoke-token'][keyof EndpointsErrors['i___revoke-token']]; + // @public (undocumented) type IRevokeTokenRequest = operations['i___revoke-token']['requestBody']['content']['application/json']; // @public (undocumented) function isAPIError(reason: Record): reason is APIError; +// @public (undocumented) +type ISigninHistoryErrors = EndpointsErrors['i___signin-history'][keyof EndpointsErrors['i___signin-history']]; + // @public (undocumented) type ISigninHistoryRequest = operations['i___signin-history']['requestBody']['content']['application/json']; // @public (undocumented) type ISigninHistoryResponse = operations['i___signin-history']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IUnpinErrors = EndpointsErrors['i___unpin'][keyof EndpointsErrors['i___unpin']]; + // @public (undocumented) type IUnpinRequest = operations['i___unpin']['requestBody']['content']['application/json']; // @public (undocumented) type IUnpinResponse = operations['i___unpin']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IUpdateEmailErrors = EndpointsErrors['i___update-email'][keyof EndpointsErrors['i___update-email']]; + // @public (undocumented) type IUpdateEmailRequest = operations['i___update-email']['requestBody']['content']['application/json']; // @public (undocumented) type IUpdateEmailResponse = operations['i___update-email']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IUpdateErrors = EndpointsErrors['i___update'][keyof EndpointsErrors['i___update']]; + // @public (undocumented) type IUpdateRequest = operations['i___update']['requestBody']['content']['application/json']; // @public (undocumented) type IUpdateResponse = operations['i___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IWebhooksCreateErrors = EndpointsErrors['i___webhooks___create'][keyof EndpointsErrors['i___webhooks___create']]; + // @public (undocumented) type IWebhooksCreateRequest = operations['i___webhooks___create']['requestBody']['content']['application/json']; // @public (undocumented) type IWebhooksCreateResponse = operations['i___webhooks___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IWebhooksDeleteErrors = EndpointsErrors['i___webhooks___delete'][keyof EndpointsErrors['i___webhooks___delete']]; + // @public (undocumented) type IWebhooksDeleteRequest = operations['i___webhooks___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type IWebhooksListErrors = EndpointsErrors['i___webhooks___list'][keyof EndpointsErrors['i___webhooks___list']]; + // @public (undocumented) type IWebhooksListResponse = operations['i___webhooks___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IWebhooksShowErrors = EndpointsErrors['i___webhooks___show'][keyof EndpointsErrors['i___webhooks___show']]; + // @public (undocumented) type IWebhooksShowRequest = operations['i___webhooks___show']['requestBody']['content']['application/json']; // @public (undocumented) type IWebhooksShowResponse = operations['i___webhooks___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type IWebhooksUpdateErrors = EndpointsErrors['i___webhooks___update'][keyof EndpointsErrors['i___webhooks___update']]; + // @public (undocumented) type IWebhooksUpdateRequest = operations['i___webhooks___update']['requestBody']['content']['application/json']; @@ -2324,6 +3528,9 @@ type MetaDetailed = components['schemas']['MetaDetailed']; // @public (undocumented) type MetaDetailedOnly = components['schemas']['MetaDetailedOnly']; +// @public (undocumented) +type MetaErrors = EndpointsErrors['meta'][keyof EndpointsErrors['meta']]; + // @public (undocumented) type MetaLite = components['schemas']['MetaLite']; @@ -2333,6 +3540,9 @@ type MetaRequest = operations['meta']['requestBody']['content']['application/jso // @public (undocumented) type MetaResponse = operations['meta']['responses']['200']['content']['application/json']; +// @public (undocumented) +type MiauthGenTokenErrors = EndpointsErrors['miauth___gen-token'][keyof EndpointsErrors['miauth___gen-token']]; + // @public (undocumented) type MiauthGenTokenRequest = operations['miauth___gen-token']['requestBody']['content']['application/json']; @@ -2479,15 +3689,24 @@ type ModerationLog = { // @public (undocumented) export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner"]; +// @public (undocumented) +type MuteCreateErrors = EndpointsErrors['mute___create'][keyof EndpointsErrors['mute___create']]; + // @public (undocumented) type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type MuteDeleteErrors = EndpointsErrors['mute___delete'][keyof EndpointsErrors['mute___delete']]; + // @public (undocumented) type MuteDeleteRequest = operations['mute___delete']['requestBody']['content']['application/json']; // @public (undocumented) export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"]; +// @public (undocumented) +type MuteListErrors = EndpointsErrors['mute___list'][keyof EndpointsErrors['mute___list']]; + // @public (undocumented) type MuteListRequest = operations['mute___list']['requestBody']['content']['application/json']; @@ -2497,6 +3716,9 @@ type MuteListResponse = operations['mute___list']['responses']['200']['content'] // @public (undocumented) type Muting = components['schemas']['Muting']; +// @public (undocumented) +type MyAppsErrors = EndpointsErrors['my___apps'][keyof EndpointsErrors['my___apps']]; + // @public (undocumented) type MyAppsRequest = operations['my___apps']['requestBody']['content']['application/json']; @@ -2512,96 +3734,156 @@ type NoteFavorite = components['schemas']['NoteFavorite']; // @public (undocumented) type NoteReaction = components['schemas']['NoteReaction']; +// @public (undocumented) +type NotesChildrenErrors = EndpointsErrors['notes___children'][keyof EndpointsErrors['notes___children']]; + // @public (undocumented) type NotesChildrenRequest = operations['notes___children']['requestBody']['content']['application/json']; // @public (undocumented) type NotesChildrenResponse = operations['notes___children']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesClipsErrors = EndpointsErrors['notes___clips'][keyof EndpointsErrors['notes___clips']]; + // @public (undocumented) type NotesClipsRequest = operations['notes___clips']['requestBody']['content']['application/json']; // @public (undocumented) type NotesClipsResponse = operations['notes___clips']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesConversationErrors = EndpointsErrors['notes___conversation'][keyof EndpointsErrors['notes___conversation']]; + // @public (undocumented) type NotesConversationRequest = operations['notes___conversation']['requestBody']['content']['application/json']; // @public (undocumented) type NotesConversationResponse = operations['notes___conversation']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesCreateErrors = EndpointsErrors['notes___create'][keyof EndpointsErrors['notes___create']]; + // @public (undocumented) type NotesCreateRequest = operations['notes___create']['requestBody']['content']['application/json']; // @public (undocumented) type NotesCreateResponse = operations['notes___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesDeleteErrors = EndpointsErrors['notes___delete'][keyof EndpointsErrors['notes___delete']]; + // @public (undocumented) type NotesDeleteRequest = operations['notes___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesErrors = EndpointsErrors['notes'][keyof EndpointsErrors['notes']]; + +// @public (undocumented) +type NotesFavoritesCreateErrors = EndpointsErrors['notes___favorites___create'][keyof EndpointsErrors['notes___favorites___create']]; + // @public (undocumented) type NotesFavoritesCreateRequest = operations['notes___favorites___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesFavoritesDeleteErrors = EndpointsErrors['notes___favorites___delete'][keyof EndpointsErrors['notes___favorites___delete']]; + // @public (undocumented) type NotesFavoritesDeleteRequest = operations['notes___favorites___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesFeaturedErrors = EndpointsErrors['notes___featured'][keyof EndpointsErrors['notes___featured']]; + // @public (undocumented) type NotesFeaturedRequest = operations['notes___featured']['requestBody']['content']['application/json']; // @public (undocumented) type NotesFeaturedResponse = operations['notes___featured']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesGlobalTimelineErrors = EndpointsErrors['notes___global-timeline'][keyof EndpointsErrors['notes___global-timeline']]; + // @public (undocumented) type NotesGlobalTimelineRequest = operations['notes___global-timeline']['requestBody']['content']['application/json']; // @public (undocumented) type NotesGlobalTimelineResponse = operations['notes___global-timeline']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesHybridTimelineErrors = EndpointsErrors['notes___hybrid-timeline'][keyof EndpointsErrors['notes___hybrid-timeline']]; + // @public (undocumented) type NotesHybridTimelineRequest = operations['notes___hybrid-timeline']['requestBody']['content']['application/json']; // @public (undocumented) type NotesHybridTimelineResponse = operations['notes___hybrid-timeline']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesLocalTimelineErrors = EndpointsErrors['notes___local-timeline'][keyof EndpointsErrors['notes___local-timeline']]; + // @public (undocumented) type NotesLocalTimelineRequest = operations['notes___local-timeline']['requestBody']['content']['application/json']; // @public (undocumented) type NotesLocalTimelineResponse = operations['notes___local-timeline']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesMentionsErrors = EndpointsErrors['notes___mentions'][keyof EndpointsErrors['notes___mentions']]; + // @public (undocumented) type NotesMentionsRequest = operations['notes___mentions']['requestBody']['content']['application/json']; // @public (undocumented) type NotesMentionsResponse = operations['notes___mentions']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesPollsRecommendationErrors = EndpointsErrors['notes___polls___recommendation'][keyof EndpointsErrors['notes___polls___recommendation']]; + // @public (undocumented) type NotesPollsRecommendationRequest = operations['notes___polls___recommendation']['requestBody']['content']['application/json']; // @public (undocumented) type NotesPollsRecommendationResponse = operations['notes___polls___recommendation']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesPollsVoteErrors = EndpointsErrors['notes___polls___vote'][keyof EndpointsErrors['notes___polls___vote']]; + // @public (undocumented) type NotesPollsVoteRequest = operations['notes___polls___vote']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesReactionsCreateErrors = EndpointsErrors['notes___reactions___create'][keyof EndpointsErrors['notes___reactions___create']]; + // @public (undocumented) type NotesReactionsCreateRequest = operations['notes___reactions___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesReactionsDeleteErrors = EndpointsErrors['notes___reactions___delete'][keyof EndpointsErrors['notes___reactions___delete']]; + // @public (undocumented) type NotesReactionsDeleteRequest = operations['notes___reactions___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesReactionsErrors = EndpointsErrors['notes___reactions'][keyof EndpointsErrors['notes___reactions']]; + // @public (undocumented) type NotesReactionsRequest = operations['notes___reactions']['requestBody']['content']['application/json']; // @public (undocumented) type NotesReactionsResponse = operations['notes___reactions']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesRenotesErrors = EndpointsErrors['notes___renotes'][keyof EndpointsErrors['notes___renotes']]; + // @public (undocumented) type NotesRenotesRequest = operations['notes___renotes']['requestBody']['content']['application/json']; // @public (undocumented) type NotesRenotesResponse = operations['notes___renotes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesRepliesErrors = EndpointsErrors['notes___replies'][keyof EndpointsErrors['notes___replies']]; + // @public (undocumented) type NotesRepliesRequest = operations['notes___replies']['requestBody']['content']['application/json']; @@ -2614,51 +3896,81 @@ type NotesRequest = operations['notes']['requestBody']['content']['application/j // @public (undocumented) type NotesResponse = operations['notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesSearchByTagErrors = EndpointsErrors['notes___search-by-tag'][keyof EndpointsErrors['notes___search-by-tag']]; + // @public (undocumented) type NotesSearchByTagRequest = operations['notes___search-by-tag']['requestBody']['content']['application/json']; // @public (undocumented) type NotesSearchByTagResponse = operations['notes___search-by-tag']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesSearchErrors = EndpointsErrors['notes___search'][keyof EndpointsErrors['notes___search']]; + // @public (undocumented) type NotesSearchRequest = operations['notes___search']['requestBody']['content']['application/json']; // @public (undocumented) type NotesSearchResponse = operations['notes___search']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesShowErrors = EndpointsErrors['notes___show'][keyof EndpointsErrors['notes___show']]; + // @public (undocumented) type NotesShowRequest = operations['notes___show']['requestBody']['content']['application/json']; // @public (undocumented) type NotesShowResponse = operations['notes___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesStateErrors = EndpointsErrors['notes___state'][keyof EndpointsErrors['notes___state']]; + // @public (undocumented) type NotesStateRequest = operations['notes___state']['requestBody']['content']['application/json']; // @public (undocumented) type NotesStateResponse = operations['notes___state']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesThreadMutingCreateErrors = EndpointsErrors['notes___thread-muting___create'][keyof EndpointsErrors['notes___thread-muting___create']]; + // @public (undocumented) type NotesThreadMutingCreateRequest = operations['notes___thread-muting___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesThreadMutingDeleteErrors = EndpointsErrors['notes___thread-muting___delete'][keyof EndpointsErrors['notes___thread-muting___delete']]; + // @public (undocumented) type NotesThreadMutingDeleteRequest = operations['notes___thread-muting___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesTimelineErrors = EndpointsErrors['notes___timeline'][keyof EndpointsErrors['notes___timeline']]; + // @public (undocumented) type NotesTimelineRequest = operations['notes___timeline']['requestBody']['content']['application/json']; // @public (undocumented) type NotesTimelineResponse = operations['notes___timeline']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesTranslateErrors = EndpointsErrors['notes___translate'][keyof EndpointsErrors['notes___translate']]; + // @public (undocumented) type NotesTranslateRequest = operations['notes___translate']['requestBody']['content']['application/json']; // @public (undocumented) type NotesTranslateResponse = operations['notes___translate']['responses']['200']['content']['application/json']; +// @public (undocumented) +type NotesUnrenoteErrors = EndpointsErrors['notes___unrenote'][keyof EndpointsErrors['notes___unrenote']]; + // @public (undocumented) type NotesUnrenoteRequest = operations['notes___unrenote']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotesUserListTimelineErrors = EndpointsErrors['notes___user-list-timeline'][keyof EndpointsErrors['notes___user-list-timeline']]; + // @public (undocumented) type NotesUserListTimelineRequest = operations['notes___user-list-timeline']['requestBody']['content']['application/json']; @@ -2671,9 +3983,21 @@ export const noteVisibilities: readonly ["public", "home", "followers", "specifi // @public (undocumented) type Notification_2 = components['schemas']['Notification']; +// @public (undocumented) +type NotificationsCreateErrors = EndpointsErrors['notifications___create'][keyof EndpointsErrors['notifications___create']]; + // @public (undocumented) type NotificationsCreateRequest = operations['notifications___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type NotificationsFlushErrors = EndpointsErrors['notifications___flush'][keyof EndpointsErrors['notifications___flush']]; + +// @public (undocumented) +type NotificationsMarkAllAsReadErrors = EndpointsErrors['notifications___mark-all-as-read'][keyof EndpointsErrors['notifications___mark-all-as-read']]; + +// @public (undocumented) +type NotificationsTestNotificationErrors = EndpointsErrors['notifications___test-notification'][keyof EndpointsErrors['notifications___test-notification']]; + // @public (undocumented) export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "achievementEarned"]; @@ -2692,33 +4016,57 @@ type PageEvent = { user: User; }; +// @public (undocumented) +type PagePushErrors = EndpointsErrors['page-push'][keyof EndpointsErrors['page-push']]; + // @public (undocumented) type PagePushRequest = operations['page-push']['requestBody']['content']['application/json']; +// @public (undocumented) +type PagesCreateErrors = EndpointsErrors['pages___create'][keyof EndpointsErrors['pages___create']]; + // @public (undocumented) type PagesCreateRequest = operations['pages___create']['requestBody']['content']['application/json']; // @public (undocumented) type PagesCreateResponse = operations['pages___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type PagesDeleteErrors = EndpointsErrors['pages___delete'][keyof EndpointsErrors['pages___delete']]; + // @public (undocumented) type PagesDeleteRequest = operations['pages___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type PagesFeaturedErrors = EndpointsErrors['pages___featured'][keyof EndpointsErrors['pages___featured']]; + // @public (undocumented) type PagesFeaturedResponse = operations['pages___featured']['responses']['200']['content']['application/json']; +// @public (undocumented) +type PagesLikeErrors = EndpointsErrors['pages___like'][keyof EndpointsErrors['pages___like']]; + // @public (undocumented) type PagesLikeRequest = operations['pages___like']['requestBody']['content']['application/json']; +// @public (undocumented) +type PagesShowErrors = EndpointsErrors['pages___show'][keyof EndpointsErrors['pages___show']]; + // @public (undocumented) type PagesShowRequest = operations['pages___show']['requestBody']['content']['application/json']; // @public (undocumented) type PagesShowResponse = operations['pages___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type PagesUnlikeErrors = EndpointsErrors['pages___unlike'][keyof EndpointsErrors['pages___unlike']]; + // @public (undocumented) type PagesUnlikeRequest = operations['pages___unlike']['requestBody']['content']['application/json']; +// @public (undocumented) +type PagesUpdateErrors = EndpointsErrors['pages___update'][keyof EndpointsErrors['pages___update']]; + // @public (undocumented) type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json']; @@ -2728,12 +4076,21 @@ function parse(acct: string): Acct; // @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"]; +// @public (undocumented) +type PingErrors = EndpointsErrors['ping'][keyof EndpointsErrors['ping']]; + // @public (undocumented) type PingResponse = operations['ping']['responses']['200']['content']['application/json']; +// @public (undocumented) +type PinnedUsersErrors = EndpointsErrors['pinned-users'][keyof EndpointsErrors['pinned-users']]; + // @public (undocumented) type PinnedUsersResponse = operations['pinned-users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type PromoReadErrors = EndpointsErrors['promo___read'][keyof EndpointsErrors['promo___read']]; + // @public (undocumented) type PromoReadRequest = operations['promo___read']['requestBody']['content']['application/json']; @@ -2759,12 +4116,21 @@ type QueueStats = { // @public (undocumented) type QueueStatsLog = QueueStats[]; +// @public (undocumented) +type RenoteMuteCreateErrors = EndpointsErrors['renote-mute___create'][keyof EndpointsErrors['renote-mute___create']]; + // @public (undocumented) type RenoteMuteCreateRequest = operations['renote-mute___create']['requestBody']['content']['application/json']; +// @public (undocumented) +type RenoteMuteDeleteErrors = EndpointsErrors['renote-mute___delete'][keyof EndpointsErrors['renote-mute___delete']]; + // @public (undocumented) type RenoteMuteDeleteRequest = operations['renote-mute___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type RenoteMuteListErrors = EndpointsErrors['renote-mute___list'][keyof EndpointsErrors['renote-mute___list']]; + // @public (undocumented) type RenoteMuteListRequest = operations['renote-mute___list']['requestBody']['content']['application/json']; @@ -2774,15 +4140,30 @@ type RenoteMuteListResponse = operations['renote-mute___list']['responses']['200 // @public (undocumented) type RenoteMuting = components['schemas']['RenoteMuting']; +// @public (undocumented) +type RequestResetPasswordErrors = EndpointsErrors['request-reset-password'][keyof EndpointsErrors['request-reset-password']]; + // @public (undocumented) type RequestResetPasswordRequest = operations['request-reset-password']['requestBody']['content']['application/json']; +// @public (undocumented) +type ResetDbErrors = EndpointsErrors['reset-db'][keyof EndpointsErrors['reset-db']]; + +// @public (undocumented) +type ResetPasswordErrors = EndpointsErrors['reset-password'][keyof EndpointsErrors['reset-password']]; + // @public (undocumented) type ResetPasswordRequest = operations['reset-password']['requestBody']['content']['application/json']; +// @public (undocumented) +type RetentionErrors = EndpointsErrors['retention'][keyof EndpointsErrors['retention']]; + // @public (undocumented) type RetentionResponse = operations['retention']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ReversiCancelMatchErrors = EndpointsErrors['reversi___cancel-match'][keyof EndpointsErrors['reversi___cancel-match']]; + // @public (undocumented) type ReversiCancelMatchRequest = operations['reversi___cancel-match']['requestBody']['content']['application/json']; @@ -2792,30 +4173,48 @@ type ReversiGameDetailed = components['schemas']['ReversiGameDetailed']; // @public (undocumented) type ReversiGameLite = components['schemas']['ReversiGameLite']; +// @public (undocumented) +type ReversiGamesErrors = EndpointsErrors['reversi___games'][keyof EndpointsErrors['reversi___games']]; + // @public (undocumented) type ReversiGamesRequest = operations['reversi___games']['requestBody']['content']['application/json']; // @public (undocumented) type ReversiGamesResponse = operations['reversi___games']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ReversiInvitationsErrors = EndpointsErrors['reversi___invitations'][keyof EndpointsErrors['reversi___invitations']]; + // @public (undocumented) type ReversiInvitationsResponse = operations['reversi___invitations']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ReversiMatchErrors = EndpointsErrors['reversi___match'][keyof EndpointsErrors['reversi___match']]; + // @public (undocumented) type ReversiMatchRequest = operations['reversi___match']['requestBody']['content']['application/json']; // @public (undocumented) type ReversiMatchResponse = operations['reversi___match']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ReversiShowGameErrors = EndpointsErrors['reversi___show-game'][keyof EndpointsErrors['reversi___show-game']]; + // @public (undocumented) type ReversiShowGameRequest = operations['reversi___show-game']['requestBody']['content']['application/json']; // @public (undocumented) type ReversiShowGameResponse = operations['reversi___show-game']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ReversiSurrenderErrors = EndpointsErrors['reversi___surrender'][keyof EndpointsErrors['reversi___surrender']]; + // @public (undocumented) type ReversiSurrenderRequest = operations['reversi___surrender']['requestBody']['content']['application/json']; +// @public (undocumented) +type ReversiVerifyErrors = EndpointsErrors['reversi___verify'][keyof EndpointsErrors['reversi___verify']]; + // @public (undocumented) type ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json']; @@ -2855,27 +4254,42 @@ type RoleLite = components['schemas']['RoleLite']; // @public (undocumented) type RolePolicies = components['schemas']['RolePolicies']; +// @public (undocumented) +type RolesListErrors = EndpointsErrors['roles___list'][keyof EndpointsErrors['roles___list']]; + // @public (undocumented) type RolesListResponse = operations['roles___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type RolesNotesErrors = EndpointsErrors['roles___notes'][keyof EndpointsErrors['roles___notes']]; + // @public (undocumented) type RolesNotesRequest = operations['roles___notes']['requestBody']['content']['application/json']; // @public (undocumented) type RolesNotesResponse = operations['roles___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type RolesShowErrors = EndpointsErrors['roles___show'][keyof EndpointsErrors['roles___show']]; + // @public (undocumented) type RolesShowRequest = operations['roles___show']['requestBody']['content']['application/json']; // @public (undocumented) type RolesShowResponse = operations['roles___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type RolesUsersErrors = EndpointsErrors['roles___users'][keyof EndpointsErrors['roles___users']]; + // @public (undocumented) type RolesUsersRequest = operations['roles___users']['requestBody']['content']['application/json']; // @public (undocumented) type RolesUsersResponse = operations['roles___users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type ServerInfoErrors = EndpointsErrors['server-info'][keyof EndpointsErrors['server-info']]; + // @public (undocumented) type ServerInfoResponse = operations['server-info']['responses']['200']['content']['application/json']; @@ -2902,6 +4316,25 @@ type ServerStatsLog = ServerStats[]; // @public (undocumented) type Signin = components['schemas']['Signin']; +// @public (undocumented) +type SigninErrors = { + message: 'Too many failed attempts to sign in. Try again later.'; + code: 'TOO_MANY_AUTHENTICATION_FAILURES'; + id: '22d05606-fbcf-421a-a2db-b32610dcfd1b'; +} | { + id: '6cc579cc-885d-43d8-95c2-b8c7fc963280'; +} | { + id: 'e03a5f46-d309-4865-9b69-56282d94e1eb'; +} | { + id: '4e30e80c-e338-45a0-8c8f-44455efa3b76'; +} | { + id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c'; +} | { + id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f'; +} | { + id: '93b86c4b-72f9-40eb-9815-798928603d1e'; +}; + // @public (undocumented) type SigninRequest = { username: string; @@ -2915,6 +4348,18 @@ type SigninResponse = { i: string; }; +// @public (undocumented) +type SignupErrors = { + message: 'DUPLICATED_USERNAME'; + code: 400; +} | { + message: 'USED_USERNAME'; + code: 400; +} | { + message: 'DENIED_USERNAME'; + code: 400; +} | Record; + // @public (undocumented) type SignupPendingRequest = { code: string; @@ -2943,6 +4388,9 @@ type SignupResponse = MeDetailed & { token: string; }; +// @public (undocumented) +type StatsErrors = EndpointsErrors['stats'][keyof EndpointsErrors['stats']]; + // @public (undocumented) type StatsResponse = operations['stats']['responses']['200']['content']['application/json']; @@ -2992,21 +4440,33 @@ export class Stream extends EventEmitter { // @public (undocumented) type SwitchCaseResponseType = Endpoints[E]['res'] extends SwitchCase ? IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : IsCaseMatched extends true ? GetCaseResult : Endpoints[E]['res']['$switch']['$default'] : Endpoints[E]['res']; +// @public (undocumented) +type SwRegisterErrors = EndpointsErrors['sw___register'][keyof EndpointsErrors['sw___register']]; + // @public (undocumented) type SwRegisterRequest = operations['sw___register']['requestBody']['content']['application/json']; // @public (undocumented) type SwRegisterResponse = operations['sw___register']['responses']['200']['content']['application/json']; +// @public (undocumented) +type SwShowRegistrationErrors = EndpointsErrors['sw___show-registration'][keyof EndpointsErrors['sw___show-registration']]; + // @public (undocumented) type SwShowRegistrationRequest = operations['sw___show-registration']['requestBody']['content']['application/json']; // @public (undocumented) type SwShowRegistrationResponse = operations['sw___show-registration']['responses']['200']['content']['application/json']; +// @public (undocumented) +type SwUnregisterErrors = EndpointsErrors['sw___unregister'][keyof EndpointsErrors['sw___unregister']]; + // @public (undocumented) type SwUnregisterRequest = operations['sw___unregister']['requestBody']['content']['application/json']; +// @public (undocumented) +type SwUpdateRegistrationErrors = EndpointsErrors['sw___update-registration'][keyof EndpointsErrors['sw___update-registration']]; + // @public (undocumented) type SwUpdateRegistrationRequest = operations['sw___update-registration']['requestBody']['content']['application/json']; @@ -3016,6 +4476,9 @@ type SwUpdateRegistrationResponse = operations['sw___update-registration']['resp // @public (undocumented) type SystemWebhook = components['schemas']['SystemWebhook']; +// @public (undocumented) +type TestErrors = EndpointsErrors['test'][keyof EndpointsErrors['test']]; + // @public (undocumented) type TestRequest = operations['test']['requestBody']['content']['application/json']; @@ -3043,60 +4506,96 @@ type UserList = components['schemas']['UserList']; // @public (undocumented) type UserLite = components['schemas']['UserLite']; +// @public (undocumented) +type UsernameAvailableErrors = EndpointsErrors['username___available'][keyof EndpointsErrors['username___available']]; + // @public (undocumented) type UsernameAvailableRequest = operations['username___available']['requestBody']['content']['application/json']; // @public (undocumented) type UsernameAvailableResponse = operations['username___available']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersAchievementsErrors = EndpointsErrors['users___achievements'][keyof EndpointsErrors['users___achievements']]; + // @public (undocumented) type UsersAchievementsRequest = operations['users___achievements']['requestBody']['content']['application/json']; // @public (undocumented) type UsersAchievementsResponse = operations['users___achievements']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersClipsErrors = EndpointsErrors['users___clips'][keyof EndpointsErrors['users___clips']]; + // @public (undocumented) type UsersClipsRequest = operations['users___clips']['requestBody']['content']['application/json']; // @public (undocumented) type UsersClipsResponse = operations['users___clips']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersErrors = EndpointsErrors['users'][keyof EndpointsErrors['users']]; + +// @public (undocumented) +type UsersFeaturedNotesErrors = EndpointsErrors['users___featured-notes'][keyof EndpointsErrors['users___featured-notes']]; + // @public (undocumented) type UsersFeaturedNotesRequest = operations['users___featured-notes']['requestBody']['content']['application/json']; // @public (undocumented) type UsersFeaturedNotesResponse = operations['users___featured-notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersFlashsErrors = EndpointsErrors['users___flashs'][keyof EndpointsErrors['users___flashs']]; + // @public (undocumented) type UsersFlashsRequest = operations['users___flashs']['requestBody']['content']['application/json']; // @public (undocumented) type UsersFlashsResponse = operations['users___flashs']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersFollowersErrors = EndpointsErrors['users___followers'][keyof EndpointsErrors['users___followers']]; + // @public (undocumented) type UsersFollowersRequest = operations['users___followers']['requestBody']['content']['application/json']; // @public (undocumented) type UsersFollowersResponse = operations['users___followers']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersFollowingErrors = EndpointsErrors['users___following'][keyof EndpointsErrors['users___following']]; + // @public (undocumented) type UsersFollowingRequest = operations['users___following']['requestBody']['content']['application/json']; // @public (undocumented) type UsersFollowingResponse = operations['users___following']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersGalleryPostsErrors = EndpointsErrors['users___gallery___posts'][keyof EndpointsErrors['users___gallery___posts']]; + // @public (undocumented) type UsersGalleryPostsRequest = operations['users___gallery___posts']['requestBody']['content']['application/json']; // @public (undocumented) type UsersGalleryPostsResponse = operations['users___gallery___posts']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersGetFrequentlyRepliedUsersErrors = EndpointsErrors['users___get-frequently-replied-users'][keyof EndpointsErrors['users___get-frequently-replied-users']]; + // @public (undocumented) type UsersGetFrequentlyRepliedUsersRequest = operations['users___get-frequently-replied-users']['requestBody']['content']['application/json']; // @public (undocumented) type UsersGetFrequentlyRepliedUsersResponse = operations['users___get-frequently-replied-users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersListsCreateErrors = EndpointsErrors['users___lists___create'][keyof EndpointsErrors['users___lists___create']]; + +// @public (undocumented) +type UsersListsCreateFromPublicErrors = EndpointsErrors['users___lists___create-from-public'][keyof EndpointsErrors['users___lists___create-from-public']]; + // @public (undocumented) type UsersListsCreateFromPublicRequest = operations['users___lists___create-from-public']['requestBody']['content']['application/json']; @@ -3109,39 +4608,69 @@ type UsersListsCreateRequest = operations['users___lists___create']['requestBody // @public (undocumented) type UsersListsCreateResponse = operations['users___lists___create']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersListsDeleteErrors = EndpointsErrors['users___lists___delete'][keyof EndpointsErrors['users___lists___delete']]; + // @public (undocumented) type UsersListsDeleteRequest = operations['users___lists___delete']['requestBody']['content']['application/json']; +// @public (undocumented) +type UsersListsFavoriteErrors = EndpointsErrors['users___lists___favorite'][keyof EndpointsErrors['users___lists___favorite']]; + // @public (undocumented) type UsersListsFavoriteRequest = operations['users___lists___favorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type UsersListsGetMembershipsErrors = EndpointsErrors['users___lists___get-memberships'][keyof EndpointsErrors['users___lists___get-memberships']]; + // @public (undocumented) type UsersListsGetMembershipsRequest = operations['users___lists___get-memberships']['requestBody']['content']['application/json']; // @public (undocumented) type UsersListsGetMembershipsResponse = operations['users___lists___get-memberships']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersListsListErrors = EndpointsErrors['users___lists___list'][keyof EndpointsErrors['users___lists___list']]; + // @public (undocumented) type UsersListsListRequest = operations['users___lists___list']['requestBody']['content']['application/json']; // @public (undocumented) type UsersListsListResponse = operations['users___lists___list']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersListsPullErrors = EndpointsErrors['users___lists___pull'][keyof EndpointsErrors['users___lists___pull']]; + // @public (undocumented) type UsersListsPullRequest = operations['users___lists___pull']['requestBody']['content']['application/json']; +// @public (undocumented) +type UsersListsPushErrors = EndpointsErrors['users___lists___push'][keyof EndpointsErrors['users___lists___push']]; + // @public (undocumented) type UsersListsPushRequest = operations['users___lists___push']['requestBody']['content']['application/json']; +// @public (undocumented) +type UsersListsShowErrors = EndpointsErrors['users___lists___show'][keyof EndpointsErrors['users___lists___show']]; + // @public (undocumented) type UsersListsShowRequest = operations['users___lists___show']['requestBody']['content']['application/json']; // @public (undocumented) type UsersListsShowResponse = operations['users___lists___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersListsUnfavoriteErrors = EndpointsErrors['users___lists___unfavorite'][keyof EndpointsErrors['users___lists___unfavorite']]; + // @public (undocumented) type UsersListsUnfavoriteRequest = operations['users___lists___unfavorite']['requestBody']['content']['application/json']; +// @public (undocumented) +type UsersListsUpdateErrors = EndpointsErrors['users___lists___update'][keyof EndpointsErrors['users___lists___update']]; + +// @public (undocumented) +type UsersListsUpdateMembershipErrors = EndpointsErrors['users___lists___update-membership'][keyof EndpointsErrors['users___lists___update-membership']]; + // @public (undocumented) type UsersListsUpdateMembershipRequest = operations['users___lists___update-membership']['requestBody']['content']['application/json']; @@ -3151,36 +4680,54 @@ type UsersListsUpdateRequest = operations['users___lists___update']['requestBody // @public (undocumented) type UsersListsUpdateResponse = operations['users___lists___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersNotesErrors = EndpointsErrors['users___notes'][keyof EndpointsErrors['users___notes']]; + // @public (undocumented) type UsersNotesRequest = operations['users___notes']['requestBody']['content']['application/json']; // @public (undocumented) type UsersNotesResponse = operations['users___notes']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersPagesErrors = EndpointsErrors['users___pages'][keyof EndpointsErrors['users___pages']]; + // @public (undocumented) type UsersPagesRequest = operations['users___pages']['requestBody']['content']['application/json']; // @public (undocumented) type UsersPagesResponse = operations['users___pages']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersReactionsErrors = EndpointsErrors['users___reactions'][keyof EndpointsErrors['users___reactions']]; + // @public (undocumented) type UsersReactionsRequest = operations['users___reactions']['requestBody']['content']['application/json']; // @public (undocumented) type UsersReactionsResponse = operations['users___reactions']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersRecommendationErrors = EndpointsErrors['users___recommendation'][keyof EndpointsErrors['users___recommendation']]; + // @public (undocumented) type UsersRecommendationRequest = operations['users___recommendation']['requestBody']['content']['application/json']; // @public (undocumented) type UsersRecommendationResponse = operations['users___recommendation']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersRelationErrors = EndpointsErrors['users___relation'][keyof EndpointsErrors['users___relation']]; + // @public (undocumented) type UsersRelationRequest = operations['users___relation']['requestBody']['content']['application/json']; // @public (undocumented) type UsersRelationResponse = operations['users___relation']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersReportAbuseErrors = EndpointsErrors['users___report-abuse'][keyof EndpointsErrors['users___report-abuse']]; + // @public (undocumented) type UsersReportAbuseRequest = operations['users___report-abuse']['requestBody']['content']['application/json']; @@ -3190,24 +4737,36 @@ type UsersRequest = operations['users']['requestBody']['content']['application/j // @public (undocumented) type UsersResponse = operations['users']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersSearchByUsernameAndHostErrors = EndpointsErrors['users___search-by-username-and-host'][keyof EndpointsErrors['users___search-by-username-and-host']]; + // @public (undocumented) type UsersSearchByUsernameAndHostRequest = operations['users___search-by-username-and-host']['requestBody']['content']['application/json']; // @public (undocumented) type UsersSearchByUsernameAndHostResponse = operations['users___search-by-username-and-host']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersSearchErrors = EndpointsErrors['users___search'][keyof EndpointsErrors['users___search']]; + // @public (undocumented) type UsersSearchRequest = operations['users___search']['requestBody']['content']['application/json']; // @public (undocumented) type UsersSearchResponse = operations['users___search']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersShowErrors = EndpointsErrors['users___show'][keyof EndpointsErrors['users___show']]; + // @public (undocumented) type UsersShowRequest = operations['users___show']['requestBody']['content']['application/json']; // @public (undocumented) type UsersShowResponse = operations['users___show']['responses']['200']['content']['application/json']; +// @public (undocumented) +type UsersUpdateMemoErrors = EndpointsErrors['users___update-memo'][keyof EndpointsErrors['users___update-memo']]; + // @public (undocumented) type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 78178d7c7e..7f21413877 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -4,15 +4,16 @@ import { toPascal } from 'ts-case-convert'; import OpenAPIParser from '@readme/openapi-parser'; import openapiTS from 'openapi-typescript'; +const disabledLints = [ + '@typescript-eslint/naming-convention', + '@typescript-eslint/no-explicit-any', +]; + async function generateBaseTypes( openApiDocs: OpenAPIV3_1.Document, openApiJsonPath: string, typeFileName: string, ) { - const disabledLints = [ - '@typescript-eslint/naming-convention', - '@typescript-eslint/no-explicit-any', - ]; const lines: string[] = []; for (const lint of disabledLints) { @@ -49,22 +50,96 @@ async function generateSchemaEntities( await writeFile(outputPath, typeAliasLines.join('\n')); } -async function generateEndpoints( - openApiDocs: OpenAPIV3_1.Document, - typeFileName: string, - entitiesOutputPath: string, - endpointOutputPath: string, -) { - const endpoints: Endpoint[] = []; - +function getEndpoints(openApiDocs: OpenAPIV3_1.Document) { // misskey-jsはPOST固定で送っているので、こちらも決め打ちする。別メソッドに対応することがあればこちらも直す必要あり const paths = openApiDocs.paths ?? {}; - const postPathItems = Object.keys(paths) + return Object.keys(paths) .map(it => ({ _path_: it.replace(/^\//, ''), ...paths[it]?.post, })) .filter(filterUndefined); +} + +async function generateEndpointErrors( + openApiDocs: OpenAPIV3_1.Document, + endpointErrorsOutputPath: string, +) { + const endpoints: Endpoint[] = []; + + const postPathItems = getEndpoints(openApiDocs); + + const endpointsErrorsOutputLine: string[] = []; + + for (const lint of disabledLints) { + endpointsErrorsOutputLine.push(`/* eslint ${lint}: 0 */`); + } + endpointsErrorsOutputLine.push(''); + + endpointsErrorsOutputLine.push('export type EndpointsErrors = {'); + + for (const operation of postPathItems) { + const path = operation._path_; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const operationId = operation.operationId!; + const endpoint = new Endpoint(path); + endpoints.push(endpoint); + + if (operation.responses) { + const okResponses = [ + '200', + '201', + '202', + '204', + ]; + + const errorResponseCodes = Object.keys(operation.responses).filter((key) => !okResponses.includes(key)); + const errorTypes = new Map(); + errorResponseCodes.forEach((code) => { + const response = operation.responses![code]; + if ('content' in response && response.content != null && 'application/json' in response.content) { + const errors = response.content['application/json'].examples; + if (errors != null) { + Object.keys(errors).forEach((key) => { + const error = errors[key]; + if (error != null && 'value' in error && error.value != null) { + errorTypes.set(key, error.value); + } + }); + } + } + }); + + if (errorTypes.size > 0) { + endpointsErrorsOutputLine.push(`\t'${operationId}': {`); + for (const [key, value] of errorTypes) { + if ('error' in value && value.error != null) { + let typeString = JSON.stringify(value.error); + typeString = typeString.substring(0, typeString.length - 1) + ', [x: string]: any ' + typeString.substring(typeString.length - 1); + endpointsErrorsOutputLine.push(`\t\t'${key}': ${typeString},`); + } + } + endpointsErrorsOutputLine.push('\t},'); + } + } + } + + endpointsErrorsOutputLine.push('};'); + endpointsErrorsOutputLine.push(''); + + await writeFile(endpointErrorsOutputPath, endpointsErrorsOutputLine.join('\n')); +} + +async function generateEndpoints( + openApiDocs: OpenAPIV3_1.Document, + typeFileName: string, + entitiesOutputPath: string, + endpointErrorsOutputPath: string, + endpointOutputPath: string, +) { + const endpoints: Endpoint[] = []; + + const postPathItems = getEndpoints(openApiDocs); for (const operation of postPathItems) { const path = operation._path_; @@ -100,6 +175,18 @@ async function generateEndpoints( ); } } + + if (operation.responses) { + const errorResponseCodes = Object.keys(operation.responses).filter((key) => key !== '200'); + if (errorResponseCodes.length > 0) { + endpoint.errors = new OperationTypeAlias( + operationId, + path, + 'application/json', + OperationsAliasType.ERRORS, + ); + } + } } const entitiesOutputLine: string[] = []; @@ -107,14 +194,16 @@ async function generateEndpoints( entitiesOutputLine.push('/* eslint @typescript-eslint/naming-convention: 0 */'); entitiesOutputLine.push(`import { operations } from '${toImportPath(typeFileName)}';`); + entitiesOutputLine.push(`import { EndpointsErrors as _Operations_EndpointsErrors } from '${toImportPath(endpointErrorsOutputPath)}';`); entitiesOutputLine.push(''); entitiesOutputLine.push(new EmptyTypeAlias(OperationsAliasType.REQUEST).toLine()); entitiesOutputLine.push(new EmptyTypeAlias(OperationsAliasType.RESPONSE).toLine()); + entitiesOutputLine.push(new EmptyTypeAlias(OperationsAliasType.ERRORS).toLine()); entitiesOutputLine.push(''); const entities = endpoints - .flatMap(it => [it.request, it.response].filter(i => i)) + .flatMap(it => [it.request, it.response, it.errors].filter(i => i)) .filter(filterUndefined); entitiesOutputLine.push(...entities.map(it => it.toLine())); entitiesOutputLine.push(''); @@ -180,6 +269,21 @@ async function generateApiClientJSDoc( endpointOutputLine.push(`import type { Endpoints } from '${toImportPath(endpointsFileName)}';`); endpointOutputLine.push(''); + endpointOutputLine.push( + `interface IErrPromise {`, + ` then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;`, + ``, + ` catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;`, + `}`, + ``, + `class ErrPromise extends Promise implements IErrPromise {`, + ` constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) {`, + ` super(executor);`, + ` }`, + `}`, + ); + endpointOutputLine.push(''); + endpointOutputLine.push(`declare module '${toImportPath(apiClientFileName)}' {`); endpointOutputLine.push(' export interface APIClient {'); for (let i = 0; i < endpoints.length; i++) { @@ -189,11 +293,11 @@ async function generateApiClientJSDoc( ' /**', ` * ${endpoint.description.split('\n').join('\n * ')}`, ' */', - ` request(`, + ` request(`, ' endpoint: E,', ' params: P,', ' credential?: string | null,', - ' ): Promise>;', + ' ): ErrPromise, RE>;', ); if (i < endpoints.length - 1) { @@ -235,7 +339,8 @@ function toImportPath(fileName: string, fromPath = '/built/autogen', toPath = '' enum OperationsAliasType { REQUEST = 'Request', - RESPONSE = 'Response' + RESPONSE = 'Response', + ERRORS = 'Errors', } interface IOperationTypeAlias { @@ -271,9 +376,15 @@ class OperationTypeAlias implements IOperationTypeAlias { toLine(): string { const name = this.generateName(); - return (this.type === OperationsAliasType.REQUEST) - ? `export type ${name} = operations['${this.operationId}']['requestBody']['content']['${this.mediaType}'];` - : `export type ${name} = operations['${this.operationId}']['responses']['200']['content']['${this.mediaType}'];`; + + switch (this.type) { + case OperationsAliasType.REQUEST: + return `export type ${name} = operations['${this.operationId}']['requestBody']['content']['${this.mediaType}'];`; + case OperationsAliasType.RESPONSE: + return `export type ${name} = operations['${this.operationId}']['responses']['200']['content']['${this.mediaType}'];`; + case OperationsAliasType.ERRORS: + return `export type ${name} = _Operations_EndpointsErrors['${this.operationId}'][keyof _Operations_EndpointsErrors['${this.operationId}']];`; + } } } @@ -296,11 +407,13 @@ class EmptyTypeAlias implements IOperationTypeAlias { const emptyRequest = new EmptyTypeAlias(OperationsAliasType.REQUEST); const emptyResponse = new EmptyTypeAlias(OperationsAliasType.RESPONSE); +const emptyErrors = new EmptyTypeAlias(OperationsAliasType.ERRORS); class Endpoint { public readonly path: string; public request?: IOperationTypeAlias; public response?: IOperationTypeAlias; + public errors?: IOperationTypeAlias; constructor(path: string) { this.path = path; @@ -309,8 +422,9 @@ class Endpoint { toLine(): string { const reqName = this.request?.generateName() ?? emptyRequest.generateName(); const resName = this.response?.generateName() ?? emptyResponse.generateName(); + const errorsName = this.errors?.generateName() ?? emptyErrors.generateName(); - return `'${this.path}': { req: ${reqName}; res: ${resName} };`; + return `'${this.path}': { req: ${reqName}; res: ${resName}; errors: ${errorsName} };`; } } @@ -324,12 +438,15 @@ async function main() { const typeFileName = './built/autogen/types.ts'; await generateBaseTypes(openApiDocs, openApiJsonPath, typeFileName); + const endpointErrorsFileName = `${generatePath}/endpointErrors.ts`; + await generateEndpointErrors(openApiDocs, endpointErrorsFileName); + const modelFileName = `${generatePath}/models.ts`; await generateSchemaEntities(openApiDocs, typeFileName, modelFileName); const entitiesFileName = `${generatePath}/entities.ts`; const endpointFileName = `${generatePath}/endpoint.ts`; - await generateEndpoints(openApiDocs, typeFileName, entitiesFileName, endpointFileName); + await generateEndpoints(openApiDocs, typeFileName, entitiesFileName, endpointErrorsFileName, endpointFileName); const apiClientWarningFileName = `${generatePath}/apiClientJSDoc.ts`; await generateApiClientJSDoc(openApiDocs, '../api.ts', endpointFileName, apiClientWarningFileName); diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index 959a634a74..2727768c70 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -3,6 +3,18 @@ import './autogen/apiClientJSDoc.js'; import { SwitchCaseResponseType } from './api.types.js'; import type { Endpoints } from './api.types.js'; +interface IErrPromise { + then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; + + catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; +} + +class ErrPromise extends Promise implements IErrPromise { + constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { + super(executor); + } +} + export type { SwitchCaseResponseType, } from './api.types.js'; @@ -49,11 +61,11 @@ export class APIClient { this.fetch = opts.fetch ?? ((...args) => fetch(...args)); } - public request( + public request( endpoint: E, params: P = {} as P, credential?: string | null, - ): Promise> { + ): ErrPromise, RE> { return new Promise((resolve, reject) => { this.fetch(`${this.origin}/api/${endpoint}`, { method: 'POST', diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts index af0bade5b3..93f90b19e5 100644 --- a/packages/misskey-js/src/api.types.ts +++ b/packages/misskey-js/src/api.types.ts @@ -1,13 +1,15 @@ import { Endpoints as Gen } from './autogen/endpoint.js'; import { UserDetailed } from './autogen/models.js'; -import { UsersShowRequest } from './autogen/entities.js'; +import { UsersShowRequest, UsersShowErrors } from './autogen/entities.js'; import { SigninRequest, SigninResponse, + SigninErrors, SignupPendingRequest, SignupPendingResponse, SignupRequest, SignupResponse, + SignupErrors, } from './entities.js'; type Overwrite = Omit< @@ -63,21 +65,25 @@ export type Endpoints = Overwrite< $default: UserDetailed; }; }; + errors: UsersShowErrors; }, // api.jsonには載せないものなのでここで定義 'signup': { req: SignupRequest; res: SignupResponse; + errors: SignupErrors; }, // api.jsonには載せないものなのでここで定義 'signup-pending': { req: SignupPendingRequest; res: SignupPendingResponse; + errors: SignupErrors; }, // api.jsonには載せないものなのでここで定義 'signin': { req: SigninRequest; res: SigninResponse; + errors: SigninErrors; }, } > diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index e799d4a0c5..11908d0f9a 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -1,6 +1,18 @@ import type { SwitchCaseResponseType } from '../api.js'; import type { Endpoints } from './endpoint.js'; +interface IErrPromise { + then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; + + catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; +} + +class ErrPromise extends Promise implements IErrPromise { + constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { + super(executor); + } +} + declare module '../api.js' { export interface APIClient { /** @@ -8,22 +20,22 @@ declare module '../api.js' { * * **Credential required**: *Yes* / **Permission**: *read:admin:meta* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-user-reports* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -31,11 +43,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -43,11 +55,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -55,11 +67,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -67,11 +79,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -79,308 +91,308 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:delete-all-files-of-a-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unset-user-avatar* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unset-user-banner* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -388,517 +400,517 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:index-stats* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:table-stats* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:user-ips* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:promo* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:reset-password* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:resolve-abuse-user-report* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:send-email* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:server-info* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-moderation-log* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:suspend-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unsuspend-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:meta* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:delete-account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:user-note* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -906,11 +918,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -918,11 +930,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -930,11 +942,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -942,11 +954,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -954,143 +966,143 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -1098,704 +1110,704 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Find the notes to which the given file is attached. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Check if a given file exists. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Upload a new drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Delete an existing drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Search for a drive file by a hash of the contents. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Search for a drive file by the given parameters. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show the properties of a drive file. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Update the properties of a drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Request the server to download a new drive file from the specified URL. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -1803,374 +1815,374 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2178,11 +2190,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2190,11 +2202,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2202,11 +2214,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2214,11 +2226,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2226,11 +2238,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2238,11 +2250,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2250,11 +2262,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2262,11 +2274,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2274,11 +2286,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2286,22 +2298,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2309,11 +2321,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2321,11 +2333,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2333,11 +2345,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2345,11 +2357,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2357,11 +2369,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2369,11 +2381,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2381,11 +2393,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2393,11 +2405,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2405,11 +2417,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2417,44 +2429,44 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2462,11 +2474,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2474,11 +2486,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2486,11 +2498,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2498,11 +2510,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2510,88 +2522,88 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2599,77 +2611,77 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2677,22 +2689,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2700,11 +2712,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2712,22 +2724,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2735,22 +2747,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2758,143 +2770,143 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -2902,462 +2914,462 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:votes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:reactions* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:reactions* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -3365,319 +3377,319 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Request a users password to be reset. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Only available when running with NODE_ENV=testing. Reset the database and flush Redis. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Complete the password reset that was previously requested. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Check push notification registration exists. @@ -3685,11 +3697,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Update push notification registration. @@ -3697,11 +3709,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Register to receive push notifications. @@ -3709,396 +3721,396 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Unregister from receiving push notifications. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Endpoint for testing input validation. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all clips this user owns. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show everyone that follows this user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show everyone that this user is following. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all gallery posts by the given user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Get a list of other users that the specified user frequently replies to. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Create a new list of users. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Delete an existing list of users. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all lists that the authenticated user has created. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Remove a user from a list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Add a user to an existing list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show the properties of a list. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Update the properties of a list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all pages this user created. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all flashs this user created. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show all reactions this user made. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show users that the authenticated user might be interested to follow. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show the different kinds of relations between the authenticated user and the specified user(s). * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * File a report. * * **Credential required**: *Yes* / **Permission**: *write:report-abuse* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Search for a user by username and/or host. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Search for users. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * Show the properties of a user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. @@ -4106,120 +4118,120 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): Promise>; + ): ErrPromise, RE>; } } diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 20c8509d4c..957d1fb262 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -2,955 +2,1334 @@ import type { EmptyRequest, EmptyResponse, AdminMetaResponse, + AdminMetaErrors, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, + AdminAbuseUserReportsErrors, AdminAbuseReportNotificationRecipientListRequest, AdminAbuseReportNotificationRecipientListResponse, + AdminAbuseReportNotificationRecipientListErrors, AdminAbuseReportNotificationRecipientShowRequest, AdminAbuseReportNotificationRecipientShowResponse, + AdminAbuseReportNotificationRecipientShowErrors, AdminAbuseReportNotificationRecipientCreateRequest, AdminAbuseReportNotificationRecipientCreateResponse, + AdminAbuseReportNotificationRecipientCreateErrors, AdminAbuseReportNotificationRecipientUpdateRequest, AdminAbuseReportNotificationRecipientUpdateResponse, + AdminAbuseReportNotificationRecipientUpdateErrors, AdminAbuseReportNotificationRecipientDeleteRequest, + AdminAbuseReportNotificationRecipientDeleteErrors, AdminAccountsCreateRequest, AdminAccountsCreateResponse, + AdminAccountsCreateErrors, AdminAccountsDeleteRequest, + AdminAccountsDeleteErrors, AdminAccountsFindByEmailRequest, AdminAccountsFindByEmailResponse, + AdminAccountsFindByEmailErrors, AdminAdCreateRequest, AdminAdCreateResponse, + AdminAdCreateErrors, AdminAdDeleteRequest, + AdminAdDeleteErrors, AdminAdListRequest, AdminAdListResponse, + AdminAdListErrors, AdminAdUpdateRequest, + AdminAdUpdateErrors, AdminAnnouncementsCreateRequest, AdminAnnouncementsCreateResponse, + AdminAnnouncementsCreateErrors, AdminAnnouncementsDeleteRequest, + AdminAnnouncementsDeleteErrors, AdminAnnouncementsListRequest, AdminAnnouncementsListResponse, + AdminAnnouncementsListErrors, AdminAnnouncementsUpdateRequest, + AdminAnnouncementsUpdateErrors, AdminAvatarDecorationsCreateRequest, + AdminAvatarDecorationsCreateErrors, AdminAvatarDecorationsDeleteRequest, + AdminAvatarDecorationsDeleteErrors, AdminAvatarDecorationsListRequest, AdminAvatarDecorationsListResponse, + AdminAvatarDecorationsListErrors, AdminAvatarDecorationsUpdateRequest, + AdminAvatarDecorationsUpdateErrors, AdminDeleteAllFilesOfAUserRequest, + AdminDeleteAllFilesOfAUserErrors, AdminUnsetUserAvatarRequest, + AdminUnsetUserAvatarErrors, AdminUnsetUserBannerRequest, + AdminUnsetUserBannerErrors, + AdminDriveCleanRemoteFilesErrors, + AdminDriveCleanupErrors, AdminDriveFilesRequest, AdminDriveFilesResponse, + AdminDriveFilesErrors, AdminDriveShowFileRequest, AdminDriveShowFileResponse, + AdminDriveShowFileErrors, AdminEmojiAddAliasesBulkRequest, + AdminEmojiAddAliasesBulkErrors, AdminEmojiAddRequest, AdminEmojiAddResponse, + AdminEmojiAddErrors, AdminEmojiCopyRequest, AdminEmojiCopyResponse, + AdminEmojiCopyErrors, AdminEmojiDeleteBulkRequest, + AdminEmojiDeleteBulkErrors, AdminEmojiDeleteRequest, + AdminEmojiDeleteErrors, AdminEmojiImportZipRequest, + AdminEmojiImportZipErrors, AdminEmojiListRemoteRequest, AdminEmojiListRemoteResponse, + AdminEmojiListRemoteErrors, AdminEmojiListRequest, AdminEmojiListResponse, + AdminEmojiListErrors, AdminEmojiRemoveAliasesBulkRequest, + AdminEmojiRemoveAliasesBulkErrors, AdminEmojiSetAliasesBulkRequest, + AdminEmojiSetAliasesBulkErrors, AdminEmojiSetCategoryBulkRequest, + AdminEmojiSetCategoryBulkErrors, AdminEmojiSetLicenseBulkRequest, + AdminEmojiSetLicenseBulkErrors, AdminEmojiUpdateRequest, + AdminEmojiUpdateErrors, AdminFederationDeleteAllFilesRequest, + AdminFederationDeleteAllFilesErrors, AdminFederationRefreshRemoteInstanceMetadataRequest, + AdminFederationRefreshRemoteInstanceMetadataErrors, AdminFederationRemoveAllFollowingRequest, + AdminFederationRemoveAllFollowingErrors, AdminFederationUpdateInstanceRequest, + AdminFederationUpdateInstanceErrors, AdminGetIndexStatsResponse, + AdminGetIndexStatsErrors, AdminGetTableStatsResponse, + AdminGetTableStatsErrors, AdminGetUserIpsRequest, AdminGetUserIpsResponse, + AdminGetUserIpsErrors, AdminInviteCreateRequest, AdminInviteCreateResponse, + AdminInviteCreateErrors, AdminInviteListRequest, AdminInviteListResponse, + AdminInviteListErrors, AdminPromoCreateRequest, + AdminPromoCreateErrors, + AdminQueueClearErrors, AdminQueueDeliverDelayedResponse, + AdminQueueDeliverDelayedErrors, AdminQueueInboxDelayedResponse, + AdminQueueInboxDelayedErrors, AdminQueuePromoteRequest, + AdminQueuePromoteErrors, AdminQueueStatsResponse, + AdminQueueStatsErrors, AdminRelaysAddRequest, AdminRelaysAddResponse, + AdminRelaysAddErrors, AdminRelaysListResponse, + AdminRelaysListErrors, AdminRelaysRemoveRequest, + AdminRelaysRemoveErrors, AdminResetPasswordRequest, AdminResetPasswordResponse, + AdminResetPasswordErrors, AdminResolveAbuseUserReportRequest, + AdminResolveAbuseUserReportErrors, AdminSendEmailRequest, + AdminSendEmailErrors, AdminServerInfoResponse, + AdminServerInfoErrors, AdminShowModerationLogsRequest, AdminShowModerationLogsResponse, + AdminShowModerationLogsErrors, AdminShowUserRequest, AdminShowUserResponse, + AdminShowUserErrors, AdminShowUsersRequest, AdminShowUsersResponse, + AdminShowUsersErrors, AdminSuspendUserRequest, + AdminSuspendUserErrors, AdminUnsuspendUserRequest, + AdminUnsuspendUserErrors, AdminUpdateMetaRequest, + AdminUpdateMetaErrors, AdminDeleteAccountRequest, + AdminDeleteAccountErrors, AdminUpdateUserNoteRequest, + AdminUpdateUserNoteErrors, AdminRolesCreateRequest, AdminRolesCreateResponse, + AdminRolesCreateErrors, AdminRolesDeleteRequest, + AdminRolesDeleteErrors, AdminRolesListResponse, + AdminRolesListErrors, AdminRolesShowRequest, AdminRolesShowResponse, + AdminRolesShowErrors, AdminRolesUpdateRequest, + AdminRolesUpdateErrors, AdminRolesAssignRequest, + AdminRolesAssignErrors, AdminRolesUnassignRequest, + AdminRolesUnassignErrors, AdminRolesUpdateDefaultPoliciesRequest, + AdminRolesUpdateDefaultPoliciesErrors, AdminRolesUsersRequest, AdminRolesUsersResponse, + AdminRolesUsersErrors, AdminSystemWebhookCreateRequest, AdminSystemWebhookCreateResponse, + AdminSystemWebhookCreateErrors, AdminSystemWebhookDeleteRequest, + AdminSystemWebhookDeleteErrors, AdminSystemWebhookListRequest, AdminSystemWebhookListResponse, + AdminSystemWebhookListErrors, AdminSystemWebhookShowRequest, AdminSystemWebhookShowResponse, + AdminSystemWebhookShowErrors, AdminSystemWebhookUpdateRequest, AdminSystemWebhookUpdateResponse, + AdminSystemWebhookUpdateErrors, AnnouncementsRequest, AnnouncementsResponse, + AnnouncementsErrors, AnnouncementsShowRequest, AnnouncementsShowResponse, + AnnouncementsShowErrors, AntennasCreateRequest, AntennasCreateResponse, + AntennasCreateErrors, AntennasDeleteRequest, + AntennasDeleteErrors, AntennasListResponse, + AntennasListErrors, AntennasNotesRequest, AntennasNotesResponse, + AntennasNotesErrors, AntennasShowRequest, AntennasShowResponse, + AntennasShowErrors, AntennasUpdateRequest, AntennasUpdateResponse, + AntennasUpdateErrors, ApGetRequest, ApGetResponse, + ApGetErrors, ApShowRequest, ApShowResponse, + ApShowErrors, AppCreateRequest, AppCreateResponse, + AppCreateErrors, AppShowRequest, AppShowResponse, + AppShowErrors, AuthAcceptRequest, + AuthAcceptErrors, AuthSessionGenerateRequest, AuthSessionGenerateResponse, + AuthSessionGenerateErrors, AuthSessionShowRequest, AuthSessionShowResponse, + AuthSessionShowErrors, AuthSessionUserkeyRequest, AuthSessionUserkeyResponse, + AuthSessionUserkeyErrors, BlockingCreateRequest, BlockingCreateResponse, + BlockingCreateErrors, BlockingDeleteRequest, BlockingDeleteResponse, + BlockingDeleteErrors, BlockingListRequest, BlockingListResponse, + BlockingListErrors, ChannelsCreateRequest, ChannelsCreateResponse, + ChannelsCreateErrors, ChannelsFeaturedResponse, + ChannelsFeaturedErrors, ChannelsFollowRequest, + ChannelsFollowErrors, ChannelsFollowedRequest, ChannelsFollowedResponse, + ChannelsFollowedErrors, ChannelsOwnedRequest, ChannelsOwnedResponse, + ChannelsOwnedErrors, ChannelsShowRequest, ChannelsShowResponse, + ChannelsShowErrors, ChannelsTimelineRequest, ChannelsTimelineResponse, + ChannelsTimelineErrors, ChannelsUnfollowRequest, + ChannelsUnfollowErrors, ChannelsUpdateRequest, ChannelsUpdateResponse, + ChannelsUpdateErrors, ChannelsFavoriteRequest, + ChannelsFavoriteErrors, ChannelsUnfavoriteRequest, + ChannelsUnfavoriteErrors, ChannelsMyFavoritesResponse, + ChannelsMyFavoritesErrors, ChannelsSearchRequest, ChannelsSearchResponse, + ChannelsSearchErrors, ChartsActiveUsersRequest, ChartsActiveUsersResponse, + ChartsActiveUsersErrors, ChartsApRequestRequest, ChartsApRequestResponse, + ChartsApRequestErrors, ChartsDriveRequest, ChartsDriveResponse, + ChartsDriveErrors, ChartsFederationRequest, ChartsFederationResponse, + ChartsFederationErrors, ChartsInstanceRequest, ChartsInstanceResponse, + ChartsInstanceErrors, ChartsNotesRequest, ChartsNotesResponse, + ChartsNotesErrors, ChartsUserDriveRequest, ChartsUserDriveResponse, + ChartsUserDriveErrors, ChartsUserFollowingRequest, ChartsUserFollowingResponse, + ChartsUserFollowingErrors, ChartsUserNotesRequest, ChartsUserNotesResponse, + ChartsUserNotesErrors, ChartsUserPvRequest, ChartsUserPvResponse, + ChartsUserPvErrors, ChartsUserReactionsRequest, ChartsUserReactionsResponse, + ChartsUserReactionsErrors, ChartsUsersRequest, ChartsUsersResponse, + ChartsUsersErrors, ClipsAddNoteRequest, + ClipsAddNoteErrors, ClipsRemoveNoteRequest, + ClipsRemoveNoteErrors, ClipsCreateRequest, ClipsCreateResponse, + ClipsCreateErrors, ClipsDeleteRequest, + ClipsDeleteErrors, ClipsListResponse, + ClipsListErrors, ClipsNotesRequest, ClipsNotesResponse, + ClipsNotesErrors, ClipsShowRequest, ClipsShowResponse, + ClipsShowErrors, ClipsUpdateRequest, ClipsUpdateResponse, + ClipsUpdateErrors, ClipsFavoriteRequest, + ClipsFavoriteErrors, ClipsUnfavoriteRequest, + ClipsUnfavoriteErrors, ClipsMyFavoritesResponse, + ClipsMyFavoritesErrors, DriveResponse, + DriveErrors, DriveFilesRequest, DriveFilesResponse, + DriveFilesErrors, DriveFilesAttachedNotesRequest, DriveFilesAttachedNotesResponse, + DriveFilesAttachedNotesErrors, DriveFilesCheckExistenceRequest, DriveFilesCheckExistenceResponse, + DriveFilesCheckExistenceErrors, DriveFilesCreateRequest, DriveFilesCreateResponse, + DriveFilesCreateErrors, DriveFilesDeleteRequest, + DriveFilesDeleteErrors, DriveFilesFindByHashRequest, DriveFilesFindByHashResponse, + DriveFilesFindByHashErrors, DriveFilesFindRequest, DriveFilesFindResponse, + DriveFilesFindErrors, DriveFilesShowRequest, DriveFilesShowResponse, + DriveFilesShowErrors, DriveFilesUpdateRequest, DriveFilesUpdateResponse, + DriveFilesUpdateErrors, DriveFilesUploadFromUrlRequest, + DriveFilesUploadFromUrlErrors, DriveFoldersRequest, DriveFoldersResponse, + DriveFoldersErrors, DriveFoldersCreateRequest, DriveFoldersCreateResponse, + DriveFoldersCreateErrors, DriveFoldersDeleteRequest, + DriveFoldersDeleteErrors, DriveFoldersFindRequest, DriveFoldersFindResponse, + DriveFoldersFindErrors, DriveFoldersShowRequest, DriveFoldersShowResponse, + DriveFoldersShowErrors, DriveFoldersUpdateRequest, DriveFoldersUpdateResponse, + DriveFoldersUpdateErrors, DriveStreamRequest, DriveStreamResponse, + DriveStreamErrors, EmailAddressAvailableRequest, EmailAddressAvailableResponse, + EmailAddressAvailableErrors, EndpointRequest, EndpointResponse, + EndpointErrors, EndpointsResponse, + EndpointsErrors, + ExportCustomEmojisErrors, FederationFollowersRequest, FederationFollowersResponse, + FederationFollowersErrors, FederationFollowingRequest, FederationFollowingResponse, + FederationFollowingErrors, FederationInstancesRequest, FederationInstancesResponse, + FederationInstancesErrors, FederationShowInstanceRequest, FederationShowInstanceResponse, + FederationShowInstanceErrors, FederationUpdateRemoteUserRequest, + FederationUpdateRemoteUserErrors, FederationUsersRequest, FederationUsersResponse, + FederationUsersErrors, FederationStatsRequest, FederationStatsResponse, + FederationStatsErrors, FollowingCreateRequest, FollowingCreateResponse, + FollowingCreateErrors, FollowingDeleteRequest, FollowingDeleteResponse, + FollowingDeleteErrors, FollowingUpdateRequest, FollowingUpdateResponse, + FollowingUpdateErrors, FollowingUpdateAllRequest, + FollowingUpdateAllErrors, FollowingInvalidateRequest, FollowingInvalidateResponse, + FollowingInvalidateErrors, FollowingRequestsAcceptRequest, + FollowingRequestsAcceptErrors, FollowingRequestsCancelRequest, FollowingRequestsCancelResponse, + FollowingRequestsCancelErrors, FollowingRequestsListRequest, FollowingRequestsListResponse, + FollowingRequestsListErrors, FollowingRequestsRejectRequest, + FollowingRequestsRejectErrors, GalleryFeaturedRequest, GalleryFeaturedResponse, + GalleryFeaturedErrors, GalleryPopularResponse, + GalleryPopularErrors, GalleryPostsRequest, GalleryPostsResponse, + GalleryPostsErrors, GalleryPostsCreateRequest, GalleryPostsCreateResponse, + GalleryPostsCreateErrors, GalleryPostsDeleteRequest, + GalleryPostsDeleteErrors, GalleryPostsLikeRequest, + GalleryPostsLikeErrors, GalleryPostsShowRequest, GalleryPostsShowResponse, + GalleryPostsShowErrors, GalleryPostsUnlikeRequest, + GalleryPostsUnlikeErrors, GalleryPostsUpdateRequest, GalleryPostsUpdateResponse, + GalleryPostsUpdateErrors, GetOnlineUsersCountResponse, + GetOnlineUsersCountErrors, GetAvatarDecorationsResponse, + GetAvatarDecorationsErrors, HashtagsListRequest, HashtagsListResponse, + HashtagsListErrors, HashtagsSearchRequest, HashtagsSearchResponse, + HashtagsSearchErrors, HashtagsShowRequest, HashtagsShowResponse, + HashtagsShowErrors, HashtagsTrendResponse, + HashtagsTrendErrors, HashtagsUsersRequest, HashtagsUsersResponse, + HashtagsUsersErrors, IResponse, + IErrors, I2faDoneRequest, I2faDoneResponse, + I2faDoneErrors, I2faKeyDoneRequest, I2faKeyDoneResponse, + I2faKeyDoneErrors, I2faPasswordLessRequest, + I2faPasswordLessErrors, I2faRegisterKeyRequest, I2faRegisterKeyResponse, + I2faRegisterKeyErrors, I2faRegisterRequest, I2faRegisterResponse, + I2faRegisterErrors, I2faUpdateKeyRequest, + I2faUpdateKeyErrors, I2faRemoveKeyRequest, + I2faRemoveKeyErrors, I2faUnregisterRequest, + I2faUnregisterErrors, IAppsRequest, IAppsResponse, + IAppsErrors, IAuthorizedAppsRequest, IAuthorizedAppsResponse, + IAuthorizedAppsErrors, IClaimAchievementRequest, + IClaimAchievementErrors, IChangePasswordRequest, + IChangePasswordErrors, IDeleteAccountRequest, + IDeleteAccountErrors, + IExportBlockingErrors, IExportFollowingRequest, + IExportFollowingErrors, + IExportMuteErrors, + IExportNotesErrors, + IExportClipsErrors, + IExportFavoritesErrors, + IExportUserListsErrors, + IExportAntennasErrors, IFavoritesRequest, IFavoritesResponse, + IFavoritesErrors, IGalleryLikesRequest, IGalleryLikesResponse, + IGalleryLikesErrors, IGalleryPostsRequest, IGalleryPostsResponse, + IGalleryPostsErrors, IImportBlockingRequest, + IImportBlockingErrors, IImportFollowingRequest, + IImportFollowingErrors, IImportMutingRequest, + IImportMutingErrors, IImportUserListsRequest, + IImportUserListsErrors, IImportAntennasRequest, + IImportAntennasErrors, INotificationsRequest, INotificationsResponse, + INotificationsErrors, INotificationsGroupedRequest, INotificationsGroupedResponse, + INotificationsGroupedErrors, IPageLikesRequest, IPageLikesResponse, + IPageLikesErrors, IPagesRequest, IPagesResponse, + IPagesErrors, IPinRequest, IPinResponse, + IPinErrors, + IReadAllUnreadNotesErrors, IReadAnnouncementRequest, + IReadAnnouncementErrors, IRegenerateTokenRequest, + IRegenerateTokenErrors, IRegistryGetAllRequest, IRegistryGetAllResponse, + IRegistryGetAllErrors, IRegistryGetDetailRequest, IRegistryGetDetailResponse, + IRegistryGetDetailErrors, IRegistryGetRequest, IRegistryGetResponse, + IRegistryGetErrors, IRegistryKeysWithTypeRequest, IRegistryKeysWithTypeResponse, + IRegistryKeysWithTypeErrors, IRegistryKeysRequest, IRegistryKeysResponse, + IRegistryKeysErrors, IRegistryRemoveRequest, + IRegistryRemoveErrors, IRegistryScopesWithDomainResponse, + IRegistryScopesWithDomainErrors, IRegistrySetRequest, + IRegistrySetErrors, IRevokeTokenRequest, + IRevokeTokenErrors, ISigninHistoryRequest, ISigninHistoryResponse, + ISigninHistoryErrors, IUnpinRequest, IUnpinResponse, + IUnpinErrors, IUpdateEmailRequest, IUpdateEmailResponse, + IUpdateEmailErrors, IUpdateRequest, IUpdateResponse, + IUpdateErrors, IMoveRequest, IMoveResponse, + IMoveErrors, IWebhooksCreateRequest, IWebhooksCreateResponse, + IWebhooksCreateErrors, IWebhooksListResponse, + IWebhooksListErrors, IWebhooksShowRequest, IWebhooksShowResponse, + IWebhooksShowErrors, IWebhooksUpdateRequest, + IWebhooksUpdateErrors, IWebhooksDeleteRequest, + IWebhooksDeleteErrors, InviteCreateResponse, + InviteCreateErrors, InviteDeleteRequest, + InviteDeleteErrors, InviteListRequest, InviteListResponse, + InviteListErrors, InviteLimitResponse, + InviteLimitErrors, MetaRequest, MetaResponse, + MetaErrors, EmojisResponse, + EmojisErrors, EmojiRequest, EmojiResponse, + EmojiErrors, MiauthGenTokenRequest, MiauthGenTokenResponse, + MiauthGenTokenErrors, MuteCreateRequest, + MuteCreateErrors, MuteDeleteRequest, + MuteDeleteErrors, MuteListRequest, MuteListResponse, + MuteListErrors, RenoteMuteCreateRequest, + RenoteMuteCreateErrors, RenoteMuteDeleteRequest, + RenoteMuteDeleteErrors, RenoteMuteListRequest, RenoteMuteListResponse, + RenoteMuteListErrors, MyAppsRequest, MyAppsResponse, + MyAppsErrors, NotesRequest, NotesResponse, + NotesErrors, NotesChildrenRequest, NotesChildrenResponse, + NotesChildrenErrors, NotesClipsRequest, NotesClipsResponse, + NotesClipsErrors, NotesConversationRequest, NotesConversationResponse, + NotesConversationErrors, NotesCreateRequest, NotesCreateResponse, + NotesCreateErrors, NotesDeleteRequest, + NotesDeleteErrors, NotesFavoritesCreateRequest, + NotesFavoritesCreateErrors, NotesFavoritesDeleteRequest, + NotesFavoritesDeleteErrors, NotesFeaturedRequest, NotesFeaturedResponse, + NotesFeaturedErrors, NotesGlobalTimelineRequest, NotesGlobalTimelineResponse, + NotesGlobalTimelineErrors, NotesHybridTimelineRequest, NotesHybridTimelineResponse, + NotesHybridTimelineErrors, NotesLocalTimelineRequest, NotesLocalTimelineResponse, + NotesLocalTimelineErrors, NotesMentionsRequest, NotesMentionsResponse, + NotesMentionsErrors, NotesPollsRecommendationRequest, NotesPollsRecommendationResponse, + NotesPollsRecommendationErrors, NotesPollsVoteRequest, + NotesPollsVoteErrors, NotesReactionsRequest, NotesReactionsResponse, + NotesReactionsErrors, NotesReactionsCreateRequest, + NotesReactionsCreateErrors, NotesReactionsDeleteRequest, + NotesReactionsDeleteErrors, NotesRenotesRequest, NotesRenotesResponse, + NotesRenotesErrors, NotesRepliesRequest, NotesRepliesResponse, + NotesRepliesErrors, NotesSearchByTagRequest, NotesSearchByTagResponse, + NotesSearchByTagErrors, NotesSearchRequest, NotesSearchResponse, + NotesSearchErrors, NotesShowRequest, NotesShowResponse, + NotesShowErrors, NotesStateRequest, NotesStateResponse, + NotesStateErrors, NotesThreadMutingCreateRequest, + NotesThreadMutingCreateErrors, NotesThreadMutingDeleteRequest, + NotesThreadMutingDeleteErrors, NotesTimelineRequest, NotesTimelineResponse, + NotesTimelineErrors, NotesTranslateRequest, NotesTranslateResponse, + NotesTranslateErrors, NotesUnrenoteRequest, + NotesUnrenoteErrors, NotesUserListTimelineRequest, NotesUserListTimelineResponse, + NotesUserListTimelineErrors, NotificationsCreateRequest, + NotificationsCreateErrors, + NotificationsFlushErrors, + NotificationsMarkAllAsReadErrors, + NotificationsTestNotificationErrors, PagePushRequest, + PagePushErrors, PagesCreateRequest, PagesCreateResponse, + PagesCreateErrors, PagesDeleteRequest, + PagesDeleteErrors, PagesFeaturedResponse, + PagesFeaturedErrors, PagesLikeRequest, + PagesLikeErrors, PagesShowRequest, PagesShowResponse, + PagesShowErrors, PagesUnlikeRequest, + PagesUnlikeErrors, PagesUpdateRequest, + PagesUpdateErrors, FlashCreateRequest, FlashCreateResponse, + FlashCreateErrors, FlashDeleteRequest, + FlashDeleteErrors, FlashFeaturedResponse, + FlashFeaturedErrors, FlashLikeRequest, + FlashLikeErrors, FlashShowRequest, FlashShowResponse, + FlashShowErrors, FlashUnlikeRequest, + FlashUnlikeErrors, FlashUpdateRequest, + FlashUpdateErrors, FlashMyRequest, FlashMyResponse, + FlashMyErrors, FlashMyLikesRequest, FlashMyLikesResponse, + FlashMyLikesErrors, PingResponse, + PingErrors, PinnedUsersResponse, + PinnedUsersErrors, PromoReadRequest, + PromoReadErrors, RolesListResponse, + RolesListErrors, RolesShowRequest, RolesShowResponse, + RolesShowErrors, RolesUsersRequest, RolesUsersResponse, + RolesUsersErrors, RolesNotesRequest, RolesNotesResponse, + RolesNotesErrors, RequestResetPasswordRequest, + RequestResetPasswordErrors, + ResetDbErrors, ResetPasswordRequest, + ResetPasswordErrors, ServerInfoResponse, + ServerInfoErrors, StatsResponse, + StatsErrors, SwShowRegistrationRequest, SwShowRegistrationResponse, + SwShowRegistrationErrors, SwUpdateRegistrationRequest, SwUpdateRegistrationResponse, + SwUpdateRegistrationErrors, SwRegisterRequest, SwRegisterResponse, + SwRegisterErrors, SwUnregisterRequest, + SwUnregisterErrors, TestRequest, TestResponse, + TestErrors, UsernameAvailableRequest, UsernameAvailableResponse, + UsernameAvailableErrors, UsersRequest, UsersResponse, + UsersErrors, UsersClipsRequest, UsersClipsResponse, + UsersClipsErrors, UsersFollowersRequest, UsersFollowersResponse, + UsersFollowersErrors, UsersFollowingRequest, UsersFollowingResponse, + UsersFollowingErrors, UsersGalleryPostsRequest, UsersGalleryPostsResponse, + UsersGalleryPostsErrors, UsersGetFrequentlyRepliedUsersRequest, UsersGetFrequentlyRepliedUsersResponse, + UsersGetFrequentlyRepliedUsersErrors, UsersFeaturedNotesRequest, UsersFeaturedNotesResponse, + UsersFeaturedNotesErrors, UsersListsCreateRequest, UsersListsCreateResponse, + UsersListsCreateErrors, UsersListsDeleteRequest, + UsersListsDeleteErrors, UsersListsListRequest, UsersListsListResponse, + UsersListsListErrors, UsersListsPullRequest, + UsersListsPullErrors, UsersListsPushRequest, + UsersListsPushErrors, UsersListsShowRequest, UsersListsShowResponse, + UsersListsShowErrors, UsersListsFavoriteRequest, + UsersListsFavoriteErrors, UsersListsUnfavoriteRequest, + UsersListsUnfavoriteErrors, UsersListsUpdateRequest, UsersListsUpdateResponse, + UsersListsUpdateErrors, UsersListsCreateFromPublicRequest, UsersListsCreateFromPublicResponse, + UsersListsCreateFromPublicErrors, UsersListsUpdateMembershipRequest, + UsersListsUpdateMembershipErrors, UsersListsGetMembershipsRequest, UsersListsGetMembershipsResponse, + UsersListsGetMembershipsErrors, UsersNotesRequest, UsersNotesResponse, + UsersNotesErrors, UsersPagesRequest, UsersPagesResponse, + UsersPagesErrors, UsersFlashsRequest, UsersFlashsResponse, + UsersFlashsErrors, UsersReactionsRequest, UsersReactionsResponse, + UsersReactionsErrors, UsersRecommendationRequest, UsersRecommendationResponse, + UsersRecommendationErrors, UsersRelationRequest, UsersRelationResponse, + UsersRelationErrors, UsersReportAbuseRequest, + UsersReportAbuseErrors, UsersSearchByUsernameAndHostRequest, UsersSearchByUsernameAndHostResponse, + UsersSearchByUsernameAndHostErrors, UsersSearchRequest, UsersSearchResponse, + UsersSearchErrors, UsersShowRequest, UsersShowResponse, + UsersShowErrors, UsersAchievementsRequest, UsersAchievementsResponse, + UsersAchievementsErrors, UsersUpdateMemoRequest, + UsersUpdateMemoErrors, FetchRssRequest, FetchRssResponse, + FetchRssErrors, FetchExternalResourcesRequest, FetchExternalResourcesResponse, + FetchExternalResourcesErrors, RetentionResponse, + RetentionErrors, BubbleGameRegisterRequest, + BubbleGameRegisterErrors, BubbleGameRankingRequest, BubbleGameRankingResponse, + BubbleGameRankingErrors, ReversiCancelMatchRequest, + ReversiCancelMatchErrors, ReversiGamesRequest, ReversiGamesResponse, + ReversiGamesErrors, ReversiMatchRequest, ReversiMatchResponse, + ReversiMatchErrors, ReversiInvitationsResponse, + ReversiInvitationsErrors, ReversiShowGameRequest, ReversiShowGameResponse, + ReversiShowGameErrors, ReversiSurrenderRequest, + ReversiSurrenderErrors, ReversiVerifyRequest, ReversiVerifyResponse, + ReversiVerifyErrors, } from './entities.js'; export type Endpoints = { - 'admin/meta': { req: EmptyRequest; res: AdminMetaResponse }; - 'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse }; - 'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse }; - 'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse }; - 'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse }; - 'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse }; - 'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse }; - 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse }; - 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse }; - 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse }; - 'admin/ad/create': { req: AdminAdCreateRequest; res: AdminAdCreateResponse }; - 'admin/ad/delete': { req: AdminAdDeleteRequest; res: EmptyResponse }; - 'admin/ad/list': { req: AdminAdListRequest; res: AdminAdListResponse }; - 'admin/ad/update': { req: AdminAdUpdateRequest; res: EmptyResponse }; - 'admin/announcements/create': { req: AdminAnnouncementsCreateRequest; res: AdminAnnouncementsCreateResponse }; - 'admin/announcements/delete': { req: AdminAnnouncementsDeleteRequest; res: EmptyResponse }; - 'admin/announcements/list': { req: AdminAnnouncementsListRequest; res: AdminAnnouncementsListResponse }; - 'admin/announcements/update': { req: AdminAnnouncementsUpdateRequest; res: EmptyResponse }; - 'admin/avatar-decorations/create': { req: AdminAvatarDecorationsCreateRequest; res: EmptyResponse }; - 'admin/avatar-decorations/delete': { req: AdminAvatarDecorationsDeleteRequest; res: EmptyResponse }; - 'admin/avatar-decorations/list': { req: AdminAvatarDecorationsListRequest; res: AdminAvatarDecorationsListResponse }; - 'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse }; - 'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse }; - 'admin/unset-user-avatar': { req: AdminUnsetUserAvatarRequest; res: EmptyResponse }; - 'admin/unset-user-banner': { req: AdminUnsetUserBannerRequest; res: EmptyResponse }; - 'admin/drive/clean-remote-files': { req: EmptyRequest; res: EmptyResponse }; - 'admin/drive/cleanup': { req: EmptyRequest; res: EmptyResponse }; - 'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse }; - 'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse }; - 'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse }; - 'admin/emoji/add': { req: AdminEmojiAddRequest; res: AdminEmojiAddResponse }; - 'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse }; - 'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse }; - 'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse }; - 'admin/emoji/import-zip': { req: AdminEmojiImportZipRequest; res: EmptyResponse }; - 'admin/emoji/list-remote': { req: AdminEmojiListRemoteRequest; res: AdminEmojiListRemoteResponse }; - 'admin/emoji/list': { req: AdminEmojiListRequest; res: AdminEmojiListResponse }; - 'admin/emoji/remove-aliases-bulk': { req: AdminEmojiRemoveAliasesBulkRequest; res: EmptyResponse }; - 'admin/emoji/set-aliases-bulk': { req: AdminEmojiSetAliasesBulkRequest; res: EmptyResponse }; - 'admin/emoji/set-category-bulk': { req: AdminEmojiSetCategoryBulkRequest; res: EmptyResponse }; - 'admin/emoji/set-license-bulk': { req: AdminEmojiSetLicenseBulkRequest; res: EmptyResponse }; - 'admin/emoji/update': { req: AdminEmojiUpdateRequest; res: EmptyResponse }; - 'admin/federation/delete-all-files': { req: AdminFederationDeleteAllFilesRequest; res: EmptyResponse }; - 'admin/federation/refresh-remote-instance-metadata': { req: AdminFederationRefreshRemoteInstanceMetadataRequest; res: EmptyResponse }; - 'admin/federation/remove-all-following': { req: AdminFederationRemoveAllFollowingRequest; res: EmptyResponse }; - 'admin/federation/update-instance': { req: AdminFederationUpdateInstanceRequest; res: EmptyResponse }; - 'admin/get-index-stats': { req: EmptyRequest; res: AdminGetIndexStatsResponse }; - 'admin/get-table-stats': { req: EmptyRequest; res: AdminGetTableStatsResponse }; - 'admin/get-user-ips': { req: AdminGetUserIpsRequest; res: AdminGetUserIpsResponse }; - 'admin/invite/create': { req: AdminInviteCreateRequest; res: AdminInviteCreateResponse }; - 'admin/invite/list': { req: AdminInviteListRequest; res: AdminInviteListResponse }; - 'admin/promo/create': { req: AdminPromoCreateRequest; res: EmptyResponse }; - 'admin/queue/clear': { req: EmptyRequest; res: EmptyResponse }; - 'admin/queue/deliver-delayed': { req: EmptyRequest; res: AdminQueueDeliverDelayedResponse }; - 'admin/queue/inbox-delayed': { req: EmptyRequest; res: AdminQueueInboxDelayedResponse }; - 'admin/queue/promote': { req: AdminQueuePromoteRequest; res: EmptyResponse }; - 'admin/queue/stats': { req: EmptyRequest; res: AdminQueueStatsResponse }; - 'admin/relays/add': { req: AdminRelaysAddRequest; res: AdminRelaysAddResponse }; - 'admin/relays/list': { req: EmptyRequest; res: AdminRelaysListResponse }; - 'admin/relays/remove': { req: AdminRelaysRemoveRequest; res: EmptyResponse }; - 'admin/reset-password': { req: AdminResetPasswordRequest; res: AdminResetPasswordResponse }; - 'admin/resolve-abuse-user-report': { req: AdminResolveAbuseUserReportRequest; res: EmptyResponse }; - 'admin/send-email': { req: AdminSendEmailRequest; res: EmptyResponse }; - 'admin/server-info': { req: EmptyRequest; res: AdminServerInfoResponse }; - 'admin/show-moderation-logs': { req: AdminShowModerationLogsRequest; res: AdminShowModerationLogsResponse }; - 'admin/show-user': { req: AdminShowUserRequest; res: AdminShowUserResponse }; - 'admin/show-users': { req: AdminShowUsersRequest; res: AdminShowUsersResponse }; - 'admin/suspend-user': { req: AdminSuspendUserRequest; res: EmptyResponse }; - 'admin/unsuspend-user': { req: AdminUnsuspendUserRequest; res: EmptyResponse }; - 'admin/update-meta': { req: AdminUpdateMetaRequest; res: EmptyResponse }; - 'admin/delete-account': { req: AdminDeleteAccountRequest; res: EmptyResponse }; - 'admin/update-user-note': { req: AdminUpdateUserNoteRequest; res: EmptyResponse }; - 'admin/roles/create': { req: AdminRolesCreateRequest; res: AdminRolesCreateResponse }; - 'admin/roles/delete': { req: AdminRolesDeleteRequest; res: EmptyResponse }; - 'admin/roles/list': { req: EmptyRequest; res: AdminRolesListResponse }; - 'admin/roles/show': { req: AdminRolesShowRequest; res: AdminRolesShowResponse }; - 'admin/roles/update': { req: AdminRolesUpdateRequest; res: EmptyResponse }; - 'admin/roles/assign': { req: AdminRolesAssignRequest; res: EmptyResponse }; - 'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse }; - 'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse }; - 'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse }; - 'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse }; - 'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse }; - 'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse }; - 'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse }; - 'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse }; - 'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse }; - 'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse }; - 'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse }; - 'antennas/delete': { req: AntennasDeleteRequest; res: EmptyResponse }; - 'antennas/list': { req: EmptyRequest; res: AntennasListResponse }; - 'antennas/notes': { req: AntennasNotesRequest; res: AntennasNotesResponse }; - 'antennas/show': { req: AntennasShowRequest; res: AntennasShowResponse }; - 'antennas/update': { req: AntennasUpdateRequest; res: AntennasUpdateResponse }; - 'ap/get': { req: ApGetRequest; res: ApGetResponse }; - 'ap/show': { req: ApShowRequest; res: ApShowResponse }; - 'app/create': { req: AppCreateRequest; res: AppCreateResponse }; - 'app/show': { req: AppShowRequest; res: AppShowResponse }; - 'auth/accept': { req: AuthAcceptRequest; res: EmptyResponse }; - 'auth/session/generate': { req: AuthSessionGenerateRequest; res: AuthSessionGenerateResponse }; - 'auth/session/show': { req: AuthSessionShowRequest; res: AuthSessionShowResponse }; - 'auth/session/userkey': { req: AuthSessionUserkeyRequest; res: AuthSessionUserkeyResponse }; - 'blocking/create': { req: BlockingCreateRequest; res: BlockingCreateResponse }; - 'blocking/delete': { req: BlockingDeleteRequest; res: BlockingDeleteResponse }; - 'blocking/list': { req: BlockingListRequest; res: BlockingListResponse }; - 'channels/create': { req: ChannelsCreateRequest; res: ChannelsCreateResponse }; - 'channels/featured': { req: EmptyRequest; res: ChannelsFeaturedResponse }; - 'channels/follow': { req: ChannelsFollowRequest; res: EmptyResponse }; - 'channels/followed': { req: ChannelsFollowedRequest; res: ChannelsFollowedResponse }; - 'channels/owned': { req: ChannelsOwnedRequest; res: ChannelsOwnedResponse }; - 'channels/show': { req: ChannelsShowRequest; res: ChannelsShowResponse }; - 'channels/timeline': { req: ChannelsTimelineRequest; res: ChannelsTimelineResponse }; - 'channels/unfollow': { req: ChannelsUnfollowRequest; res: EmptyResponse }; - 'channels/update': { req: ChannelsUpdateRequest; res: ChannelsUpdateResponse }; - 'channels/favorite': { req: ChannelsFavoriteRequest; res: EmptyResponse }; - 'channels/unfavorite': { req: ChannelsUnfavoriteRequest; res: EmptyResponse }; - 'channels/my-favorites': { req: EmptyRequest; res: ChannelsMyFavoritesResponse }; - 'channels/search': { req: ChannelsSearchRequest; res: ChannelsSearchResponse }; - 'charts/active-users': { req: ChartsActiveUsersRequest; res: ChartsActiveUsersResponse }; - 'charts/ap-request': { req: ChartsApRequestRequest; res: ChartsApRequestResponse }; - 'charts/drive': { req: ChartsDriveRequest; res: ChartsDriveResponse }; - 'charts/federation': { req: ChartsFederationRequest; res: ChartsFederationResponse }; - 'charts/instance': { req: ChartsInstanceRequest; res: ChartsInstanceResponse }; - 'charts/notes': { req: ChartsNotesRequest; res: ChartsNotesResponse }; - 'charts/user/drive': { req: ChartsUserDriveRequest; res: ChartsUserDriveResponse }; - 'charts/user/following': { req: ChartsUserFollowingRequest; res: ChartsUserFollowingResponse }; - 'charts/user/notes': { req: ChartsUserNotesRequest; res: ChartsUserNotesResponse }; - 'charts/user/pv': { req: ChartsUserPvRequest; res: ChartsUserPvResponse }; - 'charts/user/reactions': { req: ChartsUserReactionsRequest; res: ChartsUserReactionsResponse }; - 'charts/users': { req: ChartsUsersRequest; res: ChartsUsersResponse }; - 'clips/add-note': { req: ClipsAddNoteRequest; res: EmptyResponse }; - 'clips/remove-note': { req: ClipsRemoveNoteRequest; res: EmptyResponse }; - 'clips/create': { req: ClipsCreateRequest; res: ClipsCreateResponse }; - 'clips/delete': { req: ClipsDeleteRequest; res: EmptyResponse }; - 'clips/list': { req: EmptyRequest; res: ClipsListResponse }; - 'clips/notes': { req: ClipsNotesRequest; res: ClipsNotesResponse }; - 'clips/show': { req: ClipsShowRequest; res: ClipsShowResponse }; - 'clips/update': { req: ClipsUpdateRequest; res: ClipsUpdateResponse }; - 'clips/favorite': { req: ClipsFavoriteRequest; res: EmptyResponse }; - 'clips/unfavorite': { req: ClipsUnfavoriteRequest; res: EmptyResponse }; - 'clips/my-favorites': { req: EmptyRequest; res: ClipsMyFavoritesResponse }; - 'drive': { req: EmptyRequest; res: DriveResponse }; - 'drive/files': { req: DriveFilesRequest; res: DriveFilesResponse }; - 'drive/files/attached-notes': { req: DriveFilesAttachedNotesRequest; res: DriveFilesAttachedNotesResponse }; - 'drive/files/check-existence': { req: DriveFilesCheckExistenceRequest; res: DriveFilesCheckExistenceResponse }; - 'drive/files/create': { req: DriveFilesCreateRequest; res: DriveFilesCreateResponse }; - 'drive/files/delete': { req: DriveFilesDeleteRequest; res: EmptyResponse }; - 'drive/files/find-by-hash': { req: DriveFilesFindByHashRequest; res: DriveFilesFindByHashResponse }; - 'drive/files/find': { req: DriveFilesFindRequest; res: DriveFilesFindResponse }; - 'drive/files/show': { req: DriveFilesShowRequest; res: DriveFilesShowResponse }; - 'drive/files/update': { req: DriveFilesUpdateRequest; res: DriveFilesUpdateResponse }; - 'drive/files/upload-from-url': { req: DriveFilesUploadFromUrlRequest; res: EmptyResponse }; - 'drive/folders': { req: DriveFoldersRequest; res: DriveFoldersResponse }; - 'drive/folders/create': { req: DriveFoldersCreateRequest; res: DriveFoldersCreateResponse }; - 'drive/folders/delete': { req: DriveFoldersDeleteRequest; res: EmptyResponse }; - 'drive/folders/find': { req: DriveFoldersFindRequest; res: DriveFoldersFindResponse }; - 'drive/folders/show': { req: DriveFoldersShowRequest; res: DriveFoldersShowResponse }; - 'drive/folders/update': { req: DriveFoldersUpdateRequest; res: DriveFoldersUpdateResponse }; - 'drive/stream': { req: DriveStreamRequest; res: DriveStreamResponse }; - 'email-address/available': { req: EmailAddressAvailableRequest; res: EmailAddressAvailableResponse }; - 'endpoint': { req: EndpointRequest; res: EndpointResponse }; - 'endpoints': { req: EmptyRequest; res: EndpointsResponse }; - 'export-custom-emojis': { req: EmptyRequest; res: EmptyResponse }; - 'federation/followers': { req: FederationFollowersRequest; res: FederationFollowersResponse }; - 'federation/following': { req: FederationFollowingRequest; res: FederationFollowingResponse }; - 'federation/instances': { req: FederationInstancesRequest; res: FederationInstancesResponse }; - 'federation/show-instance': { req: FederationShowInstanceRequest; res: FederationShowInstanceResponse }; - 'federation/update-remote-user': { req: FederationUpdateRemoteUserRequest; res: EmptyResponse }; - 'federation/users': { req: FederationUsersRequest; res: FederationUsersResponse }; - 'federation/stats': { req: FederationStatsRequest; res: FederationStatsResponse }; - 'following/create': { req: FollowingCreateRequest; res: FollowingCreateResponse }; - 'following/delete': { req: FollowingDeleteRequest; res: FollowingDeleteResponse }; - 'following/update': { req: FollowingUpdateRequest; res: FollowingUpdateResponse }; - 'following/update-all': { req: FollowingUpdateAllRequest; res: EmptyResponse }; - 'following/invalidate': { req: FollowingInvalidateRequest; res: FollowingInvalidateResponse }; - 'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse }; - 'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse }; - 'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse }; - 'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse }; - 'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse }; - 'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse }; - 'gallery/posts': { req: GalleryPostsRequest; res: GalleryPostsResponse }; - 'gallery/posts/create': { req: GalleryPostsCreateRequest; res: GalleryPostsCreateResponse }; - 'gallery/posts/delete': { req: GalleryPostsDeleteRequest; res: EmptyResponse }; - 'gallery/posts/like': { req: GalleryPostsLikeRequest; res: EmptyResponse }; - 'gallery/posts/show': { req: GalleryPostsShowRequest; res: GalleryPostsShowResponse }; - 'gallery/posts/unlike': { req: GalleryPostsUnlikeRequest; res: EmptyResponse }; - 'gallery/posts/update': { req: GalleryPostsUpdateRequest; res: GalleryPostsUpdateResponse }; - 'get-online-users-count': { req: EmptyRequest; res: GetOnlineUsersCountResponse }; - 'get-avatar-decorations': { req: EmptyRequest; res: GetAvatarDecorationsResponse }; - 'hashtags/list': { req: HashtagsListRequest; res: HashtagsListResponse }; - 'hashtags/search': { req: HashtagsSearchRequest; res: HashtagsSearchResponse }; - 'hashtags/show': { req: HashtagsShowRequest; res: HashtagsShowResponse }; - 'hashtags/trend': { req: EmptyRequest; res: HashtagsTrendResponse }; - 'hashtags/users': { req: HashtagsUsersRequest; res: HashtagsUsersResponse }; - 'i': { req: EmptyRequest; res: IResponse }; - 'i/2fa/done': { req: I2faDoneRequest; res: I2faDoneResponse }; - 'i/2fa/key-done': { req: I2faKeyDoneRequest; res: I2faKeyDoneResponse }; - 'i/2fa/password-less': { req: I2faPasswordLessRequest; res: EmptyResponse }; - 'i/2fa/register-key': { req: I2faRegisterKeyRequest; res: I2faRegisterKeyResponse }; - 'i/2fa/register': { req: I2faRegisterRequest; res: I2faRegisterResponse }; - 'i/2fa/update-key': { req: I2faUpdateKeyRequest; res: EmptyResponse }; - 'i/2fa/remove-key': { req: I2faRemoveKeyRequest; res: EmptyResponse }; - 'i/2fa/unregister': { req: I2faUnregisterRequest; res: EmptyResponse }; - 'i/apps': { req: IAppsRequest; res: IAppsResponse }; - 'i/authorized-apps': { req: IAuthorizedAppsRequest; res: IAuthorizedAppsResponse }; - 'i/claim-achievement': { req: IClaimAchievementRequest; res: EmptyResponse }; - 'i/change-password': { req: IChangePasswordRequest; res: EmptyResponse }; - 'i/delete-account': { req: IDeleteAccountRequest; res: EmptyResponse }; - 'i/export-blocking': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-following': { req: IExportFollowingRequest; res: EmptyResponse }; - 'i/export-mute': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-notes': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-clips': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-favorites': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-user-lists': { req: EmptyRequest; res: EmptyResponse }; - 'i/export-antennas': { req: EmptyRequest; res: EmptyResponse }; - 'i/favorites': { req: IFavoritesRequest; res: IFavoritesResponse }; - 'i/gallery/likes': { req: IGalleryLikesRequest; res: IGalleryLikesResponse }; - 'i/gallery/posts': { req: IGalleryPostsRequest; res: IGalleryPostsResponse }; - 'i/import-blocking': { req: IImportBlockingRequest; res: EmptyResponse }; - 'i/import-following': { req: IImportFollowingRequest; res: EmptyResponse }; - 'i/import-muting': { req: IImportMutingRequest; res: EmptyResponse }; - 'i/import-user-lists': { req: IImportUserListsRequest; res: EmptyResponse }; - 'i/import-antennas': { req: IImportAntennasRequest; res: EmptyResponse }; - 'i/notifications': { req: INotificationsRequest; res: INotificationsResponse }; - 'i/notifications-grouped': { req: INotificationsGroupedRequest; res: INotificationsGroupedResponse }; - 'i/page-likes': { req: IPageLikesRequest; res: IPageLikesResponse }; - 'i/pages': { req: IPagesRequest; res: IPagesResponse }; - 'i/pin': { req: IPinRequest; res: IPinResponse }; - 'i/read-all-unread-notes': { req: EmptyRequest; res: EmptyResponse }; - 'i/read-announcement': { req: IReadAnnouncementRequest; res: EmptyResponse }; - 'i/regenerate-token': { req: IRegenerateTokenRequest; res: EmptyResponse }; - 'i/registry/get-all': { req: IRegistryGetAllRequest; res: IRegistryGetAllResponse }; - 'i/registry/get-detail': { req: IRegistryGetDetailRequest; res: IRegistryGetDetailResponse }; - 'i/registry/get': { req: IRegistryGetRequest; res: IRegistryGetResponse }; - 'i/registry/keys-with-type': { req: IRegistryKeysWithTypeRequest; res: IRegistryKeysWithTypeResponse }; - 'i/registry/keys': { req: IRegistryKeysRequest; res: IRegistryKeysResponse }; - 'i/registry/remove': { req: IRegistryRemoveRequest; res: EmptyResponse }; - 'i/registry/scopes-with-domain': { req: EmptyRequest; res: IRegistryScopesWithDomainResponse }; - 'i/registry/set': { req: IRegistrySetRequest; res: EmptyResponse }; - 'i/revoke-token': { req: IRevokeTokenRequest; res: EmptyResponse }; - 'i/signin-history': { req: ISigninHistoryRequest; res: ISigninHistoryResponse }; - 'i/unpin': { req: IUnpinRequest; res: IUnpinResponse }; - 'i/update-email': { req: IUpdateEmailRequest; res: IUpdateEmailResponse }; - 'i/update': { req: IUpdateRequest; res: IUpdateResponse }; - 'i/move': { req: IMoveRequest; res: IMoveResponse }; - 'i/webhooks/create': { req: IWebhooksCreateRequest; res: IWebhooksCreateResponse }; - 'i/webhooks/list': { req: EmptyRequest; res: IWebhooksListResponse }; - 'i/webhooks/show': { req: IWebhooksShowRequest; res: IWebhooksShowResponse }; - 'i/webhooks/update': { req: IWebhooksUpdateRequest; res: EmptyResponse }; - 'i/webhooks/delete': { req: IWebhooksDeleteRequest; res: EmptyResponse }; - 'invite/create': { req: EmptyRequest; res: InviteCreateResponse }; - 'invite/delete': { req: InviteDeleteRequest; res: EmptyResponse }; - 'invite/list': { req: InviteListRequest; res: InviteListResponse }; - 'invite/limit': { req: EmptyRequest; res: InviteLimitResponse }; - 'meta': { req: MetaRequest; res: MetaResponse }; - 'emojis': { req: EmptyRequest; res: EmojisResponse }; - 'emoji': { req: EmojiRequest; res: EmojiResponse }; - 'miauth/gen-token': { req: MiauthGenTokenRequest; res: MiauthGenTokenResponse }; - 'mute/create': { req: MuteCreateRequest; res: EmptyResponse }; - 'mute/delete': { req: MuteDeleteRequest; res: EmptyResponse }; - 'mute/list': { req: MuteListRequest; res: MuteListResponse }; - 'renote-mute/create': { req: RenoteMuteCreateRequest; res: EmptyResponse }; - 'renote-mute/delete': { req: RenoteMuteDeleteRequest; res: EmptyResponse }; - 'renote-mute/list': { req: RenoteMuteListRequest; res: RenoteMuteListResponse }; - 'my/apps': { req: MyAppsRequest; res: MyAppsResponse }; - 'notes': { req: NotesRequest; res: NotesResponse }; - 'notes/children': { req: NotesChildrenRequest; res: NotesChildrenResponse }; - 'notes/clips': { req: NotesClipsRequest; res: NotesClipsResponse }; - 'notes/conversation': { req: NotesConversationRequest; res: NotesConversationResponse }; - 'notes/create': { req: NotesCreateRequest; res: NotesCreateResponse }; - 'notes/delete': { req: NotesDeleteRequest; res: EmptyResponse }; - 'notes/favorites/create': { req: NotesFavoritesCreateRequest; res: EmptyResponse }; - 'notes/favorites/delete': { req: NotesFavoritesDeleteRequest; res: EmptyResponse }; - 'notes/featured': { req: NotesFeaturedRequest; res: NotesFeaturedResponse }; - 'notes/global-timeline': { req: NotesGlobalTimelineRequest; res: NotesGlobalTimelineResponse }; - 'notes/hybrid-timeline': { req: NotesHybridTimelineRequest; res: NotesHybridTimelineResponse }; - 'notes/local-timeline': { req: NotesLocalTimelineRequest; res: NotesLocalTimelineResponse }; - 'notes/mentions': { req: NotesMentionsRequest; res: NotesMentionsResponse }; - 'notes/polls/recommendation': { req: NotesPollsRecommendationRequest; res: NotesPollsRecommendationResponse }; - 'notes/polls/vote': { req: NotesPollsVoteRequest; res: EmptyResponse }; - 'notes/reactions': { req: NotesReactionsRequest; res: NotesReactionsResponse }; - 'notes/reactions/create': { req: NotesReactionsCreateRequest; res: EmptyResponse }; - 'notes/reactions/delete': { req: NotesReactionsDeleteRequest; res: EmptyResponse }; - 'notes/renotes': { req: NotesRenotesRequest; res: NotesRenotesResponse }; - 'notes/replies': { req: NotesRepliesRequest; res: NotesRepliesResponse }; - 'notes/search-by-tag': { req: NotesSearchByTagRequest; res: NotesSearchByTagResponse }; - 'notes/search': { req: NotesSearchRequest; res: NotesSearchResponse }; - 'notes/show': { req: NotesShowRequest; res: NotesShowResponse }; - 'notes/state': { req: NotesStateRequest; res: NotesStateResponse }; - 'notes/thread-muting/create': { req: NotesThreadMutingCreateRequest; res: EmptyResponse }; - 'notes/thread-muting/delete': { req: NotesThreadMutingDeleteRequest; res: EmptyResponse }; - 'notes/timeline': { req: NotesTimelineRequest; res: NotesTimelineResponse }; - 'notes/translate': { req: NotesTranslateRequest; res: NotesTranslateResponse }; - 'notes/unrenote': { req: NotesUnrenoteRequest; res: EmptyResponse }; - 'notes/user-list-timeline': { req: NotesUserListTimelineRequest; res: NotesUserListTimelineResponse }; - 'notifications/create': { req: NotificationsCreateRequest; res: EmptyResponse }; - 'notifications/flush': { req: EmptyRequest; res: EmptyResponse }; - 'notifications/mark-all-as-read': { req: EmptyRequest; res: EmptyResponse }; - 'notifications/test-notification': { req: EmptyRequest; res: EmptyResponse }; - 'page-push': { req: PagePushRequest; res: EmptyResponse }; - 'pages/create': { req: PagesCreateRequest; res: PagesCreateResponse }; - 'pages/delete': { req: PagesDeleteRequest; res: EmptyResponse }; - 'pages/featured': { req: EmptyRequest; res: PagesFeaturedResponse }; - 'pages/like': { req: PagesLikeRequest; res: EmptyResponse }; - 'pages/show': { req: PagesShowRequest; res: PagesShowResponse }; - 'pages/unlike': { req: PagesUnlikeRequest; res: EmptyResponse }; - 'pages/update': { req: PagesUpdateRequest; res: EmptyResponse }; - 'flash/create': { req: FlashCreateRequest; res: FlashCreateResponse }; - 'flash/delete': { req: FlashDeleteRequest; res: EmptyResponse }; - 'flash/featured': { req: EmptyRequest; res: FlashFeaturedResponse }; - 'flash/like': { req: FlashLikeRequest; res: EmptyResponse }; - 'flash/show': { req: FlashShowRequest; res: FlashShowResponse }; - 'flash/unlike': { req: FlashUnlikeRequest; res: EmptyResponse }; - 'flash/update': { req: FlashUpdateRequest; res: EmptyResponse }; - 'flash/my': { req: FlashMyRequest; res: FlashMyResponse }; - 'flash/my-likes': { req: FlashMyLikesRequest; res: FlashMyLikesResponse }; - 'ping': { req: EmptyRequest; res: PingResponse }; - 'pinned-users': { req: EmptyRequest; res: PinnedUsersResponse }; - 'promo/read': { req: PromoReadRequest; res: EmptyResponse }; - 'roles/list': { req: EmptyRequest; res: RolesListResponse }; - 'roles/show': { req: RolesShowRequest; res: RolesShowResponse }; - 'roles/users': { req: RolesUsersRequest; res: RolesUsersResponse }; - 'roles/notes': { req: RolesNotesRequest; res: RolesNotesResponse }; - 'request-reset-password': { req: RequestResetPasswordRequest; res: EmptyResponse }; - 'reset-db': { req: EmptyRequest; res: EmptyResponse }; - 'reset-password': { req: ResetPasswordRequest; res: EmptyResponse }; - 'server-info': { req: EmptyRequest; res: ServerInfoResponse }; - 'stats': { req: EmptyRequest; res: StatsResponse }; - 'sw/show-registration': { req: SwShowRegistrationRequest; res: SwShowRegistrationResponse }; - 'sw/update-registration': { req: SwUpdateRegistrationRequest; res: SwUpdateRegistrationResponse }; - 'sw/register': { req: SwRegisterRequest; res: SwRegisterResponse }; - 'sw/unregister': { req: SwUnregisterRequest; res: EmptyResponse }; - 'test': { req: TestRequest; res: TestResponse }; - 'username/available': { req: UsernameAvailableRequest; res: UsernameAvailableResponse }; - 'users': { req: UsersRequest; res: UsersResponse }; - 'users/clips': { req: UsersClipsRequest; res: UsersClipsResponse }; - 'users/followers': { req: UsersFollowersRequest; res: UsersFollowersResponse }; - 'users/following': { req: UsersFollowingRequest; res: UsersFollowingResponse }; - 'users/gallery/posts': { req: UsersGalleryPostsRequest; res: UsersGalleryPostsResponse }; - 'users/get-frequently-replied-users': { req: UsersGetFrequentlyRepliedUsersRequest; res: UsersGetFrequentlyRepliedUsersResponse }; - 'users/featured-notes': { req: UsersFeaturedNotesRequest; res: UsersFeaturedNotesResponse }; - 'users/lists/create': { req: UsersListsCreateRequest; res: UsersListsCreateResponse }; - 'users/lists/delete': { req: UsersListsDeleteRequest; res: EmptyResponse }; - 'users/lists/list': { req: UsersListsListRequest; res: UsersListsListResponse }; - 'users/lists/pull': { req: UsersListsPullRequest; res: EmptyResponse }; - 'users/lists/push': { req: UsersListsPushRequest; res: EmptyResponse }; - 'users/lists/show': { req: UsersListsShowRequest; res: UsersListsShowResponse }; - 'users/lists/favorite': { req: UsersListsFavoriteRequest; res: EmptyResponse }; - 'users/lists/unfavorite': { req: UsersListsUnfavoriteRequest; res: EmptyResponse }; - 'users/lists/update': { req: UsersListsUpdateRequest; res: UsersListsUpdateResponse }; - 'users/lists/create-from-public': { req: UsersListsCreateFromPublicRequest; res: UsersListsCreateFromPublicResponse }; - 'users/lists/update-membership': { req: UsersListsUpdateMembershipRequest; res: EmptyResponse }; - 'users/lists/get-memberships': { req: UsersListsGetMembershipsRequest; res: UsersListsGetMembershipsResponse }; - 'users/notes': { req: UsersNotesRequest; res: UsersNotesResponse }; - 'users/pages': { req: UsersPagesRequest; res: UsersPagesResponse }; - 'users/flashs': { req: UsersFlashsRequest; res: UsersFlashsResponse }; - 'users/reactions': { req: UsersReactionsRequest; res: UsersReactionsResponse }; - 'users/recommendation': { req: UsersRecommendationRequest; res: UsersRecommendationResponse }; - 'users/relation': { req: UsersRelationRequest; res: UsersRelationResponse }; - 'users/report-abuse': { req: UsersReportAbuseRequest; res: EmptyResponse }; - 'users/search-by-username-and-host': { req: UsersSearchByUsernameAndHostRequest; res: UsersSearchByUsernameAndHostResponse }; - 'users/search': { req: UsersSearchRequest; res: UsersSearchResponse }; - 'users/show': { req: UsersShowRequest; res: UsersShowResponse }; - 'users/achievements': { req: UsersAchievementsRequest; res: UsersAchievementsResponse }; - 'users/update-memo': { req: UsersUpdateMemoRequest; res: EmptyResponse }; - 'fetch-rss': { req: FetchRssRequest; res: FetchRssResponse }; - 'fetch-external-resources': { req: FetchExternalResourcesRequest; res: FetchExternalResourcesResponse }; - 'retention': { req: EmptyRequest; res: RetentionResponse }; - 'bubble-game/register': { req: BubbleGameRegisterRequest; res: EmptyResponse }; - 'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse }; - 'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: EmptyResponse }; - 'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse }; - 'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse }; - 'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse }; - 'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse }; - 'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse }; - 'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse }; + 'admin/meta': { req: EmptyRequest; res: AdminMetaResponse; errors: AdminMetaErrors }; + 'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse; errors: AdminAbuseUserReportsErrors }; + 'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse; errors: AdminAbuseReportNotificationRecipientListErrors }; + 'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse; errors: AdminAbuseReportNotificationRecipientShowErrors }; + 'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse; errors: AdminAbuseReportNotificationRecipientCreateErrors }; + 'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse; errors: AdminAbuseReportNotificationRecipientUpdateErrors }; + 'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse; errors: AdminAbuseReportNotificationRecipientDeleteErrors }; + 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse; errors: AdminAccountsCreateErrors }; + 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse; errors: AdminAccountsDeleteErrors }; + 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse; errors: AdminAccountsFindByEmailErrors }; + 'admin/ad/create': { req: AdminAdCreateRequest; res: AdminAdCreateResponse; errors: AdminAdCreateErrors }; + 'admin/ad/delete': { req: AdminAdDeleteRequest; res: EmptyResponse; errors: AdminAdDeleteErrors }; + 'admin/ad/list': { req: AdminAdListRequest; res: AdminAdListResponse; errors: AdminAdListErrors }; + 'admin/ad/update': { req: AdminAdUpdateRequest; res: EmptyResponse; errors: AdminAdUpdateErrors }; + 'admin/announcements/create': { req: AdminAnnouncementsCreateRequest; res: AdminAnnouncementsCreateResponse; errors: AdminAnnouncementsCreateErrors }; + 'admin/announcements/delete': { req: AdminAnnouncementsDeleteRequest; res: EmptyResponse; errors: AdminAnnouncementsDeleteErrors }; + 'admin/announcements/list': { req: AdminAnnouncementsListRequest; res: AdminAnnouncementsListResponse; errors: AdminAnnouncementsListErrors }; + 'admin/announcements/update': { req: AdminAnnouncementsUpdateRequest; res: EmptyResponse; errors: AdminAnnouncementsUpdateErrors }; + 'admin/avatar-decorations/create': { req: AdminAvatarDecorationsCreateRequest; res: EmptyResponse; errors: AdminAvatarDecorationsCreateErrors }; + 'admin/avatar-decorations/delete': { req: AdminAvatarDecorationsDeleteRequest; res: EmptyResponse; errors: AdminAvatarDecorationsDeleteErrors }; + 'admin/avatar-decorations/list': { req: AdminAvatarDecorationsListRequest; res: AdminAvatarDecorationsListResponse; errors: AdminAvatarDecorationsListErrors }; + 'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse; errors: AdminAvatarDecorationsUpdateErrors }; + 'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse; errors: AdminDeleteAllFilesOfAUserErrors }; + 'admin/unset-user-avatar': { req: AdminUnsetUserAvatarRequest; res: EmptyResponse; errors: AdminUnsetUserAvatarErrors }; + 'admin/unset-user-banner': { req: AdminUnsetUserBannerRequest; res: EmptyResponse; errors: AdminUnsetUserBannerErrors }; + 'admin/drive/clean-remote-files': { req: EmptyRequest; res: EmptyResponse; errors: AdminDriveCleanRemoteFilesErrors }; + 'admin/drive/cleanup': { req: EmptyRequest; res: EmptyResponse; errors: AdminDriveCleanupErrors }; + 'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse; errors: AdminDriveFilesErrors }; + 'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse; errors: AdminDriveShowFileErrors }; + 'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse; errors: AdminEmojiAddAliasesBulkErrors }; + 'admin/emoji/add': { req: AdminEmojiAddRequest; res: AdminEmojiAddResponse; errors: AdminEmojiAddErrors }; + 'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse; errors: AdminEmojiCopyErrors }; + 'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse; errors: AdminEmojiDeleteBulkErrors }; + 'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse; errors: AdminEmojiDeleteErrors }; + 'admin/emoji/import-zip': { req: AdminEmojiImportZipRequest; res: EmptyResponse; errors: AdminEmojiImportZipErrors }; + 'admin/emoji/list-remote': { req: AdminEmojiListRemoteRequest; res: AdminEmojiListRemoteResponse; errors: AdminEmojiListRemoteErrors }; + 'admin/emoji/list': { req: AdminEmojiListRequest; res: AdminEmojiListResponse; errors: AdminEmojiListErrors }; + 'admin/emoji/remove-aliases-bulk': { req: AdminEmojiRemoveAliasesBulkRequest; res: EmptyResponse; errors: AdminEmojiRemoveAliasesBulkErrors }; + 'admin/emoji/set-aliases-bulk': { req: AdminEmojiSetAliasesBulkRequest; res: EmptyResponse; errors: AdminEmojiSetAliasesBulkErrors }; + 'admin/emoji/set-category-bulk': { req: AdminEmojiSetCategoryBulkRequest; res: EmptyResponse; errors: AdminEmojiSetCategoryBulkErrors }; + 'admin/emoji/set-license-bulk': { req: AdminEmojiSetLicenseBulkRequest; res: EmptyResponse; errors: AdminEmojiSetLicenseBulkErrors }; + 'admin/emoji/update': { req: AdminEmojiUpdateRequest; res: EmptyResponse; errors: AdminEmojiUpdateErrors }; + 'admin/federation/delete-all-files': { req: AdminFederationDeleteAllFilesRequest; res: EmptyResponse; errors: AdminFederationDeleteAllFilesErrors }; + 'admin/federation/refresh-remote-instance-metadata': { req: AdminFederationRefreshRemoteInstanceMetadataRequest; res: EmptyResponse; errors: AdminFederationRefreshRemoteInstanceMetadataErrors }; + 'admin/federation/remove-all-following': { req: AdminFederationRemoveAllFollowingRequest; res: EmptyResponse; errors: AdminFederationRemoveAllFollowingErrors }; + 'admin/federation/update-instance': { req: AdminFederationUpdateInstanceRequest; res: EmptyResponse; errors: AdminFederationUpdateInstanceErrors }; + 'admin/get-index-stats': { req: EmptyRequest; res: AdminGetIndexStatsResponse; errors: AdminGetIndexStatsErrors }; + 'admin/get-table-stats': { req: EmptyRequest; res: AdminGetTableStatsResponse; errors: AdminGetTableStatsErrors }; + 'admin/get-user-ips': { req: AdminGetUserIpsRequest; res: AdminGetUserIpsResponse; errors: AdminGetUserIpsErrors }; + 'admin/invite/create': { req: AdminInviteCreateRequest; res: AdminInviteCreateResponse; errors: AdminInviteCreateErrors }; + 'admin/invite/list': { req: AdminInviteListRequest; res: AdminInviteListResponse; errors: AdminInviteListErrors }; + 'admin/promo/create': { req: AdminPromoCreateRequest; res: EmptyResponse; errors: AdminPromoCreateErrors }; + 'admin/queue/clear': { req: EmptyRequest; res: EmptyResponse; errors: AdminQueueClearErrors }; + 'admin/queue/deliver-delayed': { req: EmptyRequest; res: AdminQueueDeliverDelayedResponse; errors: AdminQueueDeliverDelayedErrors }; + 'admin/queue/inbox-delayed': { req: EmptyRequest; res: AdminQueueInboxDelayedResponse; errors: AdminQueueInboxDelayedErrors }; + 'admin/queue/promote': { req: AdminQueuePromoteRequest; res: EmptyResponse; errors: AdminQueuePromoteErrors }; + 'admin/queue/stats': { req: EmptyRequest; res: AdminQueueStatsResponse; errors: AdminQueueStatsErrors }; + 'admin/relays/add': { req: AdminRelaysAddRequest; res: AdminRelaysAddResponse; errors: AdminRelaysAddErrors }; + 'admin/relays/list': { req: EmptyRequest; res: AdminRelaysListResponse; errors: AdminRelaysListErrors }; + 'admin/relays/remove': { req: AdminRelaysRemoveRequest; res: EmptyResponse; errors: AdminRelaysRemoveErrors }; + 'admin/reset-password': { req: AdminResetPasswordRequest; res: AdminResetPasswordResponse; errors: AdminResetPasswordErrors }; + 'admin/resolve-abuse-user-report': { req: AdminResolveAbuseUserReportRequest; res: EmptyResponse; errors: AdminResolveAbuseUserReportErrors }; + 'admin/send-email': { req: AdminSendEmailRequest; res: EmptyResponse; errors: AdminSendEmailErrors }; + 'admin/server-info': { req: EmptyRequest; res: AdminServerInfoResponse; errors: AdminServerInfoErrors }; + 'admin/show-moderation-logs': { req: AdminShowModerationLogsRequest; res: AdminShowModerationLogsResponse; errors: AdminShowModerationLogsErrors }; + 'admin/show-user': { req: AdminShowUserRequest; res: AdminShowUserResponse; errors: AdminShowUserErrors }; + 'admin/show-users': { req: AdminShowUsersRequest; res: AdminShowUsersResponse; errors: AdminShowUsersErrors }; + 'admin/suspend-user': { req: AdminSuspendUserRequest; res: EmptyResponse; errors: AdminSuspendUserErrors }; + 'admin/unsuspend-user': { req: AdminUnsuspendUserRequest; res: EmptyResponse; errors: AdminUnsuspendUserErrors }; + 'admin/update-meta': { req: AdminUpdateMetaRequest; res: EmptyResponse; errors: AdminUpdateMetaErrors }; + 'admin/delete-account': { req: AdminDeleteAccountRequest; res: EmptyResponse; errors: AdminDeleteAccountErrors }; + 'admin/update-user-note': { req: AdminUpdateUserNoteRequest; res: EmptyResponse; errors: AdminUpdateUserNoteErrors }; + 'admin/roles/create': { req: AdminRolesCreateRequest; res: AdminRolesCreateResponse; errors: AdminRolesCreateErrors }; + 'admin/roles/delete': { req: AdminRolesDeleteRequest; res: EmptyResponse; errors: AdminRolesDeleteErrors }; + 'admin/roles/list': { req: EmptyRequest; res: AdminRolesListResponse; errors: AdminRolesListErrors }; + 'admin/roles/show': { req: AdminRolesShowRequest; res: AdminRolesShowResponse; errors: AdminRolesShowErrors }; + 'admin/roles/update': { req: AdminRolesUpdateRequest; res: EmptyResponse; errors: AdminRolesUpdateErrors }; + 'admin/roles/assign': { req: AdminRolesAssignRequest; res: EmptyResponse; errors: AdminRolesAssignErrors }; + 'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse; errors: AdminRolesUnassignErrors }; + 'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse; errors: AdminRolesUpdateDefaultPoliciesErrors }; + 'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse; errors: AdminRolesUsersErrors }; + 'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse; errors: AdminSystemWebhookCreateErrors }; + 'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse; errors: AdminSystemWebhookDeleteErrors }; + 'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse; errors: AdminSystemWebhookListErrors }; + 'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse; errors: AdminSystemWebhookShowErrors }; + 'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse; errors: AdminSystemWebhookUpdateErrors }; + 'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse; errors: AnnouncementsErrors }; + 'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse; errors: AnnouncementsShowErrors }; + 'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse; errors: AntennasCreateErrors }; + 'antennas/delete': { req: AntennasDeleteRequest; res: EmptyResponse; errors: AntennasDeleteErrors }; + 'antennas/list': { req: EmptyRequest; res: AntennasListResponse; errors: AntennasListErrors }; + 'antennas/notes': { req: AntennasNotesRequest; res: AntennasNotesResponse; errors: AntennasNotesErrors }; + 'antennas/show': { req: AntennasShowRequest; res: AntennasShowResponse; errors: AntennasShowErrors }; + 'antennas/update': { req: AntennasUpdateRequest; res: AntennasUpdateResponse; errors: AntennasUpdateErrors }; + 'ap/get': { req: ApGetRequest; res: ApGetResponse; errors: ApGetErrors }; + 'ap/show': { req: ApShowRequest; res: ApShowResponse; errors: ApShowErrors }; + 'app/create': { req: AppCreateRequest; res: AppCreateResponse; errors: AppCreateErrors }; + 'app/show': { req: AppShowRequest; res: AppShowResponse; errors: AppShowErrors }; + 'auth/accept': { req: AuthAcceptRequest; res: EmptyResponse; errors: AuthAcceptErrors }; + 'auth/session/generate': { req: AuthSessionGenerateRequest; res: AuthSessionGenerateResponse; errors: AuthSessionGenerateErrors }; + 'auth/session/show': { req: AuthSessionShowRequest; res: AuthSessionShowResponse; errors: AuthSessionShowErrors }; + 'auth/session/userkey': { req: AuthSessionUserkeyRequest; res: AuthSessionUserkeyResponse; errors: AuthSessionUserkeyErrors }; + 'blocking/create': { req: BlockingCreateRequest; res: BlockingCreateResponse; errors: BlockingCreateErrors }; + 'blocking/delete': { req: BlockingDeleteRequest; res: BlockingDeleteResponse; errors: BlockingDeleteErrors }; + 'blocking/list': { req: BlockingListRequest; res: BlockingListResponse; errors: BlockingListErrors }; + 'channels/create': { req: ChannelsCreateRequest; res: ChannelsCreateResponse; errors: ChannelsCreateErrors }; + 'channels/featured': { req: EmptyRequest; res: ChannelsFeaturedResponse; errors: ChannelsFeaturedErrors }; + 'channels/follow': { req: ChannelsFollowRequest; res: EmptyResponse; errors: ChannelsFollowErrors }; + 'channels/followed': { req: ChannelsFollowedRequest; res: ChannelsFollowedResponse; errors: ChannelsFollowedErrors }; + 'channels/owned': { req: ChannelsOwnedRequest; res: ChannelsOwnedResponse; errors: ChannelsOwnedErrors }; + 'channels/show': { req: ChannelsShowRequest; res: ChannelsShowResponse; errors: ChannelsShowErrors }; + 'channels/timeline': { req: ChannelsTimelineRequest; res: ChannelsTimelineResponse; errors: ChannelsTimelineErrors }; + 'channels/unfollow': { req: ChannelsUnfollowRequest; res: EmptyResponse; errors: ChannelsUnfollowErrors }; + 'channels/update': { req: ChannelsUpdateRequest; res: ChannelsUpdateResponse; errors: ChannelsUpdateErrors }; + 'channels/favorite': { req: ChannelsFavoriteRequest; res: EmptyResponse; errors: ChannelsFavoriteErrors }; + 'channels/unfavorite': { req: ChannelsUnfavoriteRequest; res: EmptyResponse; errors: ChannelsUnfavoriteErrors }; + 'channels/my-favorites': { req: EmptyRequest; res: ChannelsMyFavoritesResponse; errors: ChannelsMyFavoritesErrors }; + 'channels/search': { req: ChannelsSearchRequest; res: ChannelsSearchResponse; errors: ChannelsSearchErrors }; + 'charts/active-users': { req: ChartsActiveUsersRequest; res: ChartsActiveUsersResponse; errors: ChartsActiveUsersErrors }; + 'charts/ap-request': { req: ChartsApRequestRequest; res: ChartsApRequestResponse; errors: ChartsApRequestErrors }; + 'charts/drive': { req: ChartsDriveRequest; res: ChartsDriveResponse; errors: ChartsDriveErrors }; + 'charts/federation': { req: ChartsFederationRequest; res: ChartsFederationResponse; errors: ChartsFederationErrors }; + 'charts/instance': { req: ChartsInstanceRequest; res: ChartsInstanceResponse; errors: ChartsInstanceErrors }; + 'charts/notes': { req: ChartsNotesRequest; res: ChartsNotesResponse; errors: ChartsNotesErrors }; + 'charts/user/drive': { req: ChartsUserDriveRequest; res: ChartsUserDriveResponse; errors: ChartsUserDriveErrors }; + 'charts/user/following': { req: ChartsUserFollowingRequest; res: ChartsUserFollowingResponse; errors: ChartsUserFollowingErrors }; + 'charts/user/notes': { req: ChartsUserNotesRequest; res: ChartsUserNotesResponse; errors: ChartsUserNotesErrors }; + 'charts/user/pv': { req: ChartsUserPvRequest; res: ChartsUserPvResponse; errors: ChartsUserPvErrors }; + 'charts/user/reactions': { req: ChartsUserReactionsRequest; res: ChartsUserReactionsResponse; errors: ChartsUserReactionsErrors }; + 'charts/users': { req: ChartsUsersRequest; res: ChartsUsersResponse; errors: ChartsUsersErrors }; + 'clips/add-note': { req: ClipsAddNoteRequest; res: EmptyResponse; errors: ClipsAddNoteErrors }; + 'clips/remove-note': { req: ClipsRemoveNoteRequest; res: EmptyResponse; errors: ClipsRemoveNoteErrors }; + 'clips/create': { req: ClipsCreateRequest; res: ClipsCreateResponse; errors: ClipsCreateErrors }; + 'clips/delete': { req: ClipsDeleteRequest; res: EmptyResponse; errors: ClipsDeleteErrors }; + 'clips/list': { req: EmptyRequest; res: ClipsListResponse; errors: ClipsListErrors }; + 'clips/notes': { req: ClipsNotesRequest; res: ClipsNotesResponse; errors: ClipsNotesErrors }; + 'clips/show': { req: ClipsShowRequest; res: ClipsShowResponse; errors: ClipsShowErrors }; + 'clips/update': { req: ClipsUpdateRequest; res: ClipsUpdateResponse; errors: ClipsUpdateErrors }; + 'clips/favorite': { req: ClipsFavoriteRequest; res: EmptyResponse; errors: ClipsFavoriteErrors }; + 'clips/unfavorite': { req: ClipsUnfavoriteRequest; res: EmptyResponse; errors: ClipsUnfavoriteErrors }; + 'clips/my-favorites': { req: EmptyRequest; res: ClipsMyFavoritesResponse; errors: ClipsMyFavoritesErrors }; + 'drive': { req: EmptyRequest; res: DriveResponse; errors: DriveErrors }; + 'drive/files': { req: DriveFilesRequest; res: DriveFilesResponse; errors: DriveFilesErrors }; + 'drive/files/attached-notes': { req: DriveFilesAttachedNotesRequest; res: DriveFilesAttachedNotesResponse; errors: DriveFilesAttachedNotesErrors }; + 'drive/files/check-existence': { req: DriveFilesCheckExistenceRequest; res: DriveFilesCheckExistenceResponse; errors: DriveFilesCheckExistenceErrors }; + 'drive/files/create': { req: DriveFilesCreateRequest; res: DriveFilesCreateResponse; errors: DriveFilesCreateErrors }; + 'drive/files/delete': { req: DriveFilesDeleteRequest; res: EmptyResponse; errors: DriveFilesDeleteErrors }; + 'drive/files/find-by-hash': { req: DriveFilesFindByHashRequest; res: DriveFilesFindByHashResponse; errors: DriveFilesFindByHashErrors }; + 'drive/files/find': { req: DriveFilesFindRequest; res: DriveFilesFindResponse; errors: DriveFilesFindErrors }; + 'drive/files/show': { req: DriveFilesShowRequest; res: DriveFilesShowResponse; errors: DriveFilesShowErrors }; + 'drive/files/update': { req: DriveFilesUpdateRequest; res: DriveFilesUpdateResponse; errors: DriveFilesUpdateErrors }; + 'drive/files/upload-from-url': { req: DriveFilesUploadFromUrlRequest; res: EmptyResponse; errors: DriveFilesUploadFromUrlErrors }; + 'drive/folders': { req: DriveFoldersRequest; res: DriveFoldersResponse; errors: DriveFoldersErrors }; + 'drive/folders/create': { req: DriveFoldersCreateRequest; res: DriveFoldersCreateResponse; errors: DriveFoldersCreateErrors }; + 'drive/folders/delete': { req: DriveFoldersDeleteRequest; res: EmptyResponse; errors: DriveFoldersDeleteErrors }; + 'drive/folders/find': { req: DriveFoldersFindRequest; res: DriveFoldersFindResponse; errors: DriveFoldersFindErrors }; + 'drive/folders/show': { req: DriveFoldersShowRequest; res: DriveFoldersShowResponse; errors: DriveFoldersShowErrors }; + 'drive/folders/update': { req: DriveFoldersUpdateRequest; res: DriveFoldersUpdateResponse; errors: DriveFoldersUpdateErrors }; + 'drive/stream': { req: DriveStreamRequest; res: DriveStreamResponse; errors: DriveStreamErrors }; + 'email-address/available': { req: EmailAddressAvailableRequest; res: EmailAddressAvailableResponse; errors: EmailAddressAvailableErrors }; + 'endpoint': { req: EndpointRequest; res: EndpointResponse; errors: EndpointErrors }; + 'endpoints': { req: EmptyRequest; res: EndpointsResponse; errors: EndpointsErrors }; + 'export-custom-emojis': { req: EmptyRequest; res: EmptyResponse; errors: ExportCustomEmojisErrors }; + 'federation/followers': { req: FederationFollowersRequest; res: FederationFollowersResponse; errors: FederationFollowersErrors }; + 'federation/following': { req: FederationFollowingRequest; res: FederationFollowingResponse; errors: FederationFollowingErrors }; + 'federation/instances': { req: FederationInstancesRequest; res: FederationInstancesResponse; errors: FederationInstancesErrors }; + 'federation/show-instance': { req: FederationShowInstanceRequest; res: FederationShowInstanceResponse; errors: FederationShowInstanceErrors }; + 'federation/update-remote-user': { req: FederationUpdateRemoteUserRequest; res: EmptyResponse; errors: FederationUpdateRemoteUserErrors }; + 'federation/users': { req: FederationUsersRequest; res: FederationUsersResponse; errors: FederationUsersErrors }; + 'federation/stats': { req: FederationStatsRequest; res: FederationStatsResponse; errors: FederationStatsErrors }; + 'following/create': { req: FollowingCreateRequest; res: FollowingCreateResponse; errors: FollowingCreateErrors }; + 'following/delete': { req: FollowingDeleteRequest; res: FollowingDeleteResponse; errors: FollowingDeleteErrors }; + 'following/update': { req: FollowingUpdateRequest; res: FollowingUpdateResponse; errors: FollowingUpdateErrors }; + 'following/update-all': { req: FollowingUpdateAllRequest; res: EmptyResponse; errors: FollowingUpdateAllErrors }; + 'following/invalidate': { req: FollowingInvalidateRequest; res: FollowingInvalidateResponse; errors: FollowingInvalidateErrors }; + 'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse; errors: FollowingRequestsAcceptErrors }; + 'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse; errors: FollowingRequestsCancelErrors }; + 'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse; errors: FollowingRequestsListErrors }; + 'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse; errors: FollowingRequestsRejectErrors }; + 'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse; errors: GalleryFeaturedErrors }; + 'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse; errors: GalleryPopularErrors }; + 'gallery/posts': { req: GalleryPostsRequest; res: GalleryPostsResponse; errors: GalleryPostsErrors }; + 'gallery/posts/create': { req: GalleryPostsCreateRequest; res: GalleryPostsCreateResponse; errors: GalleryPostsCreateErrors }; + 'gallery/posts/delete': { req: GalleryPostsDeleteRequest; res: EmptyResponse; errors: GalleryPostsDeleteErrors }; + 'gallery/posts/like': { req: GalleryPostsLikeRequest; res: EmptyResponse; errors: GalleryPostsLikeErrors }; + 'gallery/posts/show': { req: GalleryPostsShowRequest; res: GalleryPostsShowResponse; errors: GalleryPostsShowErrors }; + 'gallery/posts/unlike': { req: GalleryPostsUnlikeRequest; res: EmptyResponse; errors: GalleryPostsUnlikeErrors }; + 'gallery/posts/update': { req: GalleryPostsUpdateRequest; res: GalleryPostsUpdateResponse; errors: GalleryPostsUpdateErrors }; + 'get-online-users-count': { req: EmptyRequest; res: GetOnlineUsersCountResponse; errors: GetOnlineUsersCountErrors }; + 'get-avatar-decorations': { req: EmptyRequest; res: GetAvatarDecorationsResponse; errors: GetAvatarDecorationsErrors }; + 'hashtags/list': { req: HashtagsListRequest; res: HashtagsListResponse; errors: HashtagsListErrors }; + 'hashtags/search': { req: HashtagsSearchRequest; res: HashtagsSearchResponse; errors: HashtagsSearchErrors }; + 'hashtags/show': { req: HashtagsShowRequest; res: HashtagsShowResponse; errors: HashtagsShowErrors }; + 'hashtags/trend': { req: EmptyRequest; res: HashtagsTrendResponse; errors: HashtagsTrendErrors }; + 'hashtags/users': { req: HashtagsUsersRequest; res: HashtagsUsersResponse; errors: HashtagsUsersErrors }; + 'i': { req: EmptyRequest; res: IResponse; errors: IErrors }; + 'i/2fa/done': { req: I2faDoneRequest; res: I2faDoneResponse; errors: I2faDoneErrors }; + 'i/2fa/key-done': { req: I2faKeyDoneRequest; res: I2faKeyDoneResponse; errors: I2faKeyDoneErrors }; + 'i/2fa/password-less': { req: I2faPasswordLessRequest; res: EmptyResponse; errors: I2faPasswordLessErrors }; + 'i/2fa/register-key': { req: I2faRegisterKeyRequest; res: I2faRegisterKeyResponse; errors: I2faRegisterKeyErrors }; + 'i/2fa/register': { req: I2faRegisterRequest; res: I2faRegisterResponse; errors: I2faRegisterErrors }; + 'i/2fa/update-key': { req: I2faUpdateKeyRequest; res: EmptyResponse; errors: I2faUpdateKeyErrors }; + 'i/2fa/remove-key': { req: I2faRemoveKeyRequest; res: EmptyResponse; errors: I2faRemoveKeyErrors }; + 'i/2fa/unregister': { req: I2faUnregisterRequest; res: EmptyResponse; errors: I2faUnregisterErrors }; + 'i/apps': { req: IAppsRequest; res: IAppsResponse; errors: IAppsErrors }; + 'i/authorized-apps': { req: IAuthorizedAppsRequest; res: IAuthorizedAppsResponse; errors: IAuthorizedAppsErrors }; + 'i/claim-achievement': { req: IClaimAchievementRequest; res: EmptyResponse; errors: IClaimAchievementErrors }; + 'i/change-password': { req: IChangePasswordRequest; res: EmptyResponse; errors: IChangePasswordErrors }; + 'i/delete-account': { req: IDeleteAccountRequest; res: EmptyResponse; errors: IDeleteAccountErrors }; + 'i/export-blocking': { req: EmptyRequest; res: EmptyResponse; errors: IExportBlockingErrors }; + 'i/export-following': { req: IExportFollowingRequest; res: EmptyResponse; errors: IExportFollowingErrors }; + 'i/export-mute': { req: EmptyRequest; res: EmptyResponse; errors: IExportMuteErrors }; + 'i/export-notes': { req: EmptyRequest; res: EmptyResponse; errors: IExportNotesErrors }; + 'i/export-clips': { req: EmptyRequest; res: EmptyResponse; errors: IExportClipsErrors }; + 'i/export-favorites': { req: EmptyRequest; res: EmptyResponse; errors: IExportFavoritesErrors }; + 'i/export-user-lists': { req: EmptyRequest; res: EmptyResponse; errors: IExportUserListsErrors }; + 'i/export-antennas': { req: EmptyRequest; res: EmptyResponse; errors: IExportAntennasErrors }; + 'i/favorites': { req: IFavoritesRequest; res: IFavoritesResponse; errors: IFavoritesErrors }; + 'i/gallery/likes': { req: IGalleryLikesRequest; res: IGalleryLikesResponse; errors: IGalleryLikesErrors }; + 'i/gallery/posts': { req: IGalleryPostsRequest; res: IGalleryPostsResponse; errors: IGalleryPostsErrors }; + 'i/import-blocking': { req: IImportBlockingRequest; res: EmptyResponse; errors: IImportBlockingErrors }; + 'i/import-following': { req: IImportFollowingRequest; res: EmptyResponse; errors: IImportFollowingErrors }; + 'i/import-muting': { req: IImportMutingRequest; res: EmptyResponse; errors: IImportMutingErrors }; + 'i/import-user-lists': { req: IImportUserListsRequest; res: EmptyResponse; errors: IImportUserListsErrors }; + 'i/import-antennas': { req: IImportAntennasRequest; res: EmptyResponse; errors: IImportAntennasErrors }; + 'i/notifications': { req: INotificationsRequest; res: INotificationsResponse; errors: INotificationsErrors }; + 'i/notifications-grouped': { req: INotificationsGroupedRequest; res: INotificationsGroupedResponse; errors: INotificationsGroupedErrors }; + 'i/page-likes': { req: IPageLikesRequest; res: IPageLikesResponse; errors: IPageLikesErrors }; + 'i/pages': { req: IPagesRequest; res: IPagesResponse; errors: IPagesErrors }; + 'i/pin': { req: IPinRequest; res: IPinResponse; errors: IPinErrors }; + 'i/read-all-unread-notes': { req: EmptyRequest; res: EmptyResponse; errors: IReadAllUnreadNotesErrors }; + 'i/read-announcement': { req: IReadAnnouncementRequest; res: EmptyResponse; errors: IReadAnnouncementErrors }; + 'i/regenerate-token': { req: IRegenerateTokenRequest; res: EmptyResponse; errors: IRegenerateTokenErrors }; + 'i/registry/get-all': { req: IRegistryGetAllRequest; res: IRegistryGetAllResponse; errors: IRegistryGetAllErrors }; + 'i/registry/get-detail': { req: IRegistryGetDetailRequest; res: IRegistryGetDetailResponse; errors: IRegistryGetDetailErrors }; + 'i/registry/get': { req: IRegistryGetRequest; res: IRegistryGetResponse; errors: IRegistryGetErrors }; + 'i/registry/keys-with-type': { req: IRegistryKeysWithTypeRequest; res: IRegistryKeysWithTypeResponse; errors: IRegistryKeysWithTypeErrors }; + 'i/registry/keys': { req: IRegistryKeysRequest; res: IRegistryKeysResponse; errors: IRegistryKeysErrors }; + 'i/registry/remove': { req: IRegistryRemoveRequest; res: EmptyResponse; errors: IRegistryRemoveErrors }; + 'i/registry/scopes-with-domain': { req: EmptyRequest; res: IRegistryScopesWithDomainResponse; errors: IRegistryScopesWithDomainErrors }; + 'i/registry/set': { req: IRegistrySetRequest; res: EmptyResponse; errors: IRegistrySetErrors }; + 'i/revoke-token': { req: IRevokeTokenRequest; res: EmptyResponse; errors: IRevokeTokenErrors }; + 'i/signin-history': { req: ISigninHistoryRequest; res: ISigninHistoryResponse; errors: ISigninHistoryErrors }; + 'i/unpin': { req: IUnpinRequest; res: IUnpinResponse; errors: IUnpinErrors }; + 'i/update-email': { req: IUpdateEmailRequest; res: IUpdateEmailResponse; errors: IUpdateEmailErrors }; + 'i/update': { req: IUpdateRequest; res: IUpdateResponse; errors: IUpdateErrors }; + 'i/move': { req: IMoveRequest; res: IMoveResponse; errors: IMoveErrors }; + 'i/webhooks/create': { req: IWebhooksCreateRequest; res: IWebhooksCreateResponse; errors: IWebhooksCreateErrors }; + 'i/webhooks/list': { req: EmptyRequest; res: IWebhooksListResponse; errors: IWebhooksListErrors }; + 'i/webhooks/show': { req: IWebhooksShowRequest; res: IWebhooksShowResponse; errors: IWebhooksShowErrors }; + 'i/webhooks/update': { req: IWebhooksUpdateRequest; res: EmptyResponse; errors: IWebhooksUpdateErrors }; + 'i/webhooks/delete': { req: IWebhooksDeleteRequest; res: EmptyResponse; errors: IWebhooksDeleteErrors }; + 'invite/create': { req: EmptyRequest; res: InviteCreateResponse; errors: InviteCreateErrors }; + 'invite/delete': { req: InviteDeleteRequest; res: EmptyResponse; errors: InviteDeleteErrors }; + 'invite/list': { req: InviteListRequest; res: InviteListResponse; errors: InviteListErrors }; + 'invite/limit': { req: EmptyRequest; res: InviteLimitResponse; errors: InviteLimitErrors }; + 'meta': { req: MetaRequest; res: MetaResponse; errors: MetaErrors }; + 'emojis': { req: EmptyRequest; res: EmojisResponse; errors: EmojisErrors }; + 'emoji': { req: EmojiRequest; res: EmojiResponse; errors: EmojiErrors }; + 'miauth/gen-token': { req: MiauthGenTokenRequest; res: MiauthGenTokenResponse; errors: MiauthGenTokenErrors }; + 'mute/create': { req: MuteCreateRequest; res: EmptyResponse; errors: MuteCreateErrors }; + 'mute/delete': { req: MuteDeleteRequest; res: EmptyResponse; errors: MuteDeleteErrors }; + 'mute/list': { req: MuteListRequest; res: MuteListResponse; errors: MuteListErrors }; + 'renote-mute/create': { req: RenoteMuteCreateRequest; res: EmptyResponse; errors: RenoteMuteCreateErrors }; + 'renote-mute/delete': { req: RenoteMuteDeleteRequest; res: EmptyResponse; errors: RenoteMuteDeleteErrors }; + 'renote-mute/list': { req: RenoteMuteListRequest; res: RenoteMuteListResponse; errors: RenoteMuteListErrors }; + 'my/apps': { req: MyAppsRequest; res: MyAppsResponse; errors: MyAppsErrors }; + 'notes': { req: NotesRequest; res: NotesResponse; errors: NotesErrors }; + 'notes/children': { req: NotesChildrenRequest; res: NotesChildrenResponse; errors: NotesChildrenErrors }; + 'notes/clips': { req: NotesClipsRequest; res: NotesClipsResponse; errors: NotesClipsErrors }; + 'notes/conversation': { req: NotesConversationRequest; res: NotesConversationResponse; errors: NotesConversationErrors }; + 'notes/create': { req: NotesCreateRequest; res: NotesCreateResponse; errors: NotesCreateErrors }; + 'notes/delete': { req: NotesDeleteRequest; res: EmptyResponse; errors: NotesDeleteErrors }; + 'notes/favorites/create': { req: NotesFavoritesCreateRequest; res: EmptyResponse; errors: NotesFavoritesCreateErrors }; + 'notes/favorites/delete': { req: NotesFavoritesDeleteRequest; res: EmptyResponse; errors: NotesFavoritesDeleteErrors }; + 'notes/featured': { req: NotesFeaturedRequest; res: NotesFeaturedResponse; errors: NotesFeaturedErrors }; + 'notes/global-timeline': { req: NotesGlobalTimelineRequest; res: NotesGlobalTimelineResponse; errors: NotesGlobalTimelineErrors }; + 'notes/hybrid-timeline': { req: NotesHybridTimelineRequest; res: NotesHybridTimelineResponse; errors: NotesHybridTimelineErrors }; + 'notes/local-timeline': { req: NotesLocalTimelineRequest; res: NotesLocalTimelineResponse; errors: NotesLocalTimelineErrors }; + 'notes/mentions': { req: NotesMentionsRequest; res: NotesMentionsResponse; errors: NotesMentionsErrors }; + 'notes/polls/recommendation': { req: NotesPollsRecommendationRequest; res: NotesPollsRecommendationResponse; errors: NotesPollsRecommendationErrors }; + 'notes/polls/vote': { req: NotesPollsVoteRequest; res: EmptyResponse; errors: NotesPollsVoteErrors }; + 'notes/reactions': { req: NotesReactionsRequest; res: NotesReactionsResponse; errors: NotesReactionsErrors }; + 'notes/reactions/create': { req: NotesReactionsCreateRequest; res: EmptyResponse; errors: NotesReactionsCreateErrors }; + 'notes/reactions/delete': { req: NotesReactionsDeleteRequest; res: EmptyResponse; errors: NotesReactionsDeleteErrors }; + 'notes/renotes': { req: NotesRenotesRequest; res: NotesRenotesResponse; errors: NotesRenotesErrors }; + 'notes/replies': { req: NotesRepliesRequest; res: NotesRepliesResponse; errors: NotesRepliesErrors }; + 'notes/search-by-tag': { req: NotesSearchByTagRequest; res: NotesSearchByTagResponse; errors: NotesSearchByTagErrors }; + 'notes/search': { req: NotesSearchRequest; res: NotesSearchResponse; errors: NotesSearchErrors }; + 'notes/show': { req: NotesShowRequest; res: NotesShowResponse; errors: NotesShowErrors }; + 'notes/state': { req: NotesStateRequest; res: NotesStateResponse; errors: NotesStateErrors }; + 'notes/thread-muting/create': { req: NotesThreadMutingCreateRequest; res: EmptyResponse; errors: NotesThreadMutingCreateErrors }; + 'notes/thread-muting/delete': { req: NotesThreadMutingDeleteRequest; res: EmptyResponse; errors: NotesThreadMutingDeleteErrors }; + 'notes/timeline': { req: NotesTimelineRequest; res: NotesTimelineResponse; errors: NotesTimelineErrors }; + 'notes/translate': { req: NotesTranslateRequest; res: NotesTranslateResponse; errors: NotesTranslateErrors }; + 'notes/unrenote': { req: NotesUnrenoteRequest; res: EmptyResponse; errors: NotesUnrenoteErrors }; + 'notes/user-list-timeline': { req: NotesUserListTimelineRequest; res: NotesUserListTimelineResponse; errors: NotesUserListTimelineErrors }; + 'notifications/create': { req: NotificationsCreateRequest; res: EmptyResponse; errors: NotificationsCreateErrors }; + 'notifications/flush': { req: EmptyRequest; res: EmptyResponse; errors: NotificationsFlushErrors }; + 'notifications/mark-all-as-read': { req: EmptyRequest; res: EmptyResponse; errors: NotificationsMarkAllAsReadErrors }; + 'notifications/test-notification': { req: EmptyRequest; res: EmptyResponse; errors: NotificationsTestNotificationErrors }; + 'page-push': { req: PagePushRequest; res: EmptyResponse; errors: PagePushErrors }; + 'pages/create': { req: PagesCreateRequest; res: PagesCreateResponse; errors: PagesCreateErrors }; + 'pages/delete': { req: PagesDeleteRequest; res: EmptyResponse; errors: PagesDeleteErrors }; + 'pages/featured': { req: EmptyRequest; res: PagesFeaturedResponse; errors: PagesFeaturedErrors }; + 'pages/like': { req: PagesLikeRequest; res: EmptyResponse; errors: PagesLikeErrors }; + 'pages/show': { req: PagesShowRequest; res: PagesShowResponse; errors: PagesShowErrors }; + 'pages/unlike': { req: PagesUnlikeRequest; res: EmptyResponse; errors: PagesUnlikeErrors }; + 'pages/update': { req: PagesUpdateRequest; res: EmptyResponse; errors: PagesUpdateErrors }; + 'flash/create': { req: FlashCreateRequest; res: FlashCreateResponse; errors: FlashCreateErrors }; + 'flash/delete': { req: FlashDeleteRequest; res: EmptyResponse; errors: FlashDeleteErrors }; + 'flash/featured': { req: EmptyRequest; res: FlashFeaturedResponse; errors: FlashFeaturedErrors }; + 'flash/like': { req: FlashLikeRequest; res: EmptyResponse; errors: FlashLikeErrors }; + 'flash/show': { req: FlashShowRequest; res: FlashShowResponse; errors: FlashShowErrors }; + 'flash/unlike': { req: FlashUnlikeRequest; res: EmptyResponse; errors: FlashUnlikeErrors }; + 'flash/update': { req: FlashUpdateRequest; res: EmptyResponse; errors: FlashUpdateErrors }; + 'flash/my': { req: FlashMyRequest; res: FlashMyResponse; errors: FlashMyErrors }; + 'flash/my-likes': { req: FlashMyLikesRequest; res: FlashMyLikesResponse; errors: FlashMyLikesErrors }; + 'ping': { req: EmptyRequest; res: PingResponse; errors: PingErrors }; + 'pinned-users': { req: EmptyRequest; res: PinnedUsersResponse; errors: PinnedUsersErrors }; + 'promo/read': { req: PromoReadRequest; res: EmptyResponse; errors: PromoReadErrors }; + 'roles/list': { req: EmptyRequest; res: RolesListResponse; errors: RolesListErrors }; + 'roles/show': { req: RolesShowRequest; res: RolesShowResponse; errors: RolesShowErrors }; + 'roles/users': { req: RolesUsersRequest; res: RolesUsersResponse; errors: RolesUsersErrors }; + 'roles/notes': { req: RolesNotesRequest; res: RolesNotesResponse; errors: RolesNotesErrors }; + 'request-reset-password': { req: RequestResetPasswordRequest; res: EmptyResponse; errors: RequestResetPasswordErrors }; + 'reset-db': { req: EmptyRequest; res: EmptyResponse; errors: ResetDbErrors }; + 'reset-password': { req: ResetPasswordRequest; res: EmptyResponse; errors: ResetPasswordErrors }; + 'server-info': { req: EmptyRequest; res: ServerInfoResponse; errors: ServerInfoErrors }; + 'stats': { req: EmptyRequest; res: StatsResponse; errors: StatsErrors }; + 'sw/show-registration': { req: SwShowRegistrationRequest; res: SwShowRegistrationResponse; errors: SwShowRegistrationErrors }; + 'sw/update-registration': { req: SwUpdateRegistrationRequest; res: SwUpdateRegistrationResponse; errors: SwUpdateRegistrationErrors }; + 'sw/register': { req: SwRegisterRequest; res: SwRegisterResponse; errors: SwRegisterErrors }; + 'sw/unregister': { req: SwUnregisterRequest; res: EmptyResponse; errors: SwUnregisterErrors }; + 'test': { req: TestRequest; res: TestResponse; errors: TestErrors }; + 'username/available': { req: UsernameAvailableRequest; res: UsernameAvailableResponse; errors: UsernameAvailableErrors }; + 'users': { req: UsersRequest; res: UsersResponse; errors: UsersErrors }; + 'users/clips': { req: UsersClipsRequest; res: UsersClipsResponse; errors: UsersClipsErrors }; + 'users/followers': { req: UsersFollowersRequest; res: UsersFollowersResponse; errors: UsersFollowersErrors }; + 'users/following': { req: UsersFollowingRequest; res: UsersFollowingResponse; errors: UsersFollowingErrors }; + 'users/gallery/posts': { req: UsersGalleryPostsRequest; res: UsersGalleryPostsResponse; errors: UsersGalleryPostsErrors }; + 'users/get-frequently-replied-users': { req: UsersGetFrequentlyRepliedUsersRequest; res: UsersGetFrequentlyRepliedUsersResponse; errors: UsersGetFrequentlyRepliedUsersErrors }; + 'users/featured-notes': { req: UsersFeaturedNotesRequest; res: UsersFeaturedNotesResponse; errors: UsersFeaturedNotesErrors }; + 'users/lists/create': { req: UsersListsCreateRequest; res: UsersListsCreateResponse; errors: UsersListsCreateErrors }; + 'users/lists/delete': { req: UsersListsDeleteRequest; res: EmptyResponse; errors: UsersListsDeleteErrors }; + 'users/lists/list': { req: UsersListsListRequest; res: UsersListsListResponse; errors: UsersListsListErrors }; + 'users/lists/pull': { req: UsersListsPullRequest; res: EmptyResponse; errors: UsersListsPullErrors }; + 'users/lists/push': { req: UsersListsPushRequest; res: EmptyResponse; errors: UsersListsPushErrors }; + 'users/lists/show': { req: UsersListsShowRequest; res: UsersListsShowResponse; errors: UsersListsShowErrors }; + 'users/lists/favorite': { req: UsersListsFavoriteRequest; res: EmptyResponse; errors: UsersListsFavoriteErrors }; + 'users/lists/unfavorite': { req: UsersListsUnfavoriteRequest; res: EmptyResponse; errors: UsersListsUnfavoriteErrors }; + 'users/lists/update': { req: UsersListsUpdateRequest; res: UsersListsUpdateResponse; errors: UsersListsUpdateErrors }; + 'users/lists/create-from-public': { req: UsersListsCreateFromPublicRequest; res: UsersListsCreateFromPublicResponse; errors: UsersListsCreateFromPublicErrors }; + 'users/lists/update-membership': { req: UsersListsUpdateMembershipRequest; res: EmptyResponse; errors: UsersListsUpdateMembershipErrors }; + 'users/lists/get-memberships': { req: UsersListsGetMembershipsRequest; res: UsersListsGetMembershipsResponse; errors: UsersListsGetMembershipsErrors }; + 'users/notes': { req: UsersNotesRequest; res: UsersNotesResponse; errors: UsersNotesErrors }; + 'users/pages': { req: UsersPagesRequest; res: UsersPagesResponse; errors: UsersPagesErrors }; + 'users/flashs': { req: UsersFlashsRequest; res: UsersFlashsResponse; errors: UsersFlashsErrors }; + 'users/reactions': { req: UsersReactionsRequest; res: UsersReactionsResponse; errors: UsersReactionsErrors }; + 'users/recommendation': { req: UsersRecommendationRequest; res: UsersRecommendationResponse; errors: UsersRecommendationErrors }; + 'users/relation': { req: UsersRelationRequest; res: UsersRelationResponse; errors: UsersRelationErrors }; + 'users/report-abuse': { req: UsersReportAbuseRequest; res: EmptyResponse; errors: UsersReportAbuseErrors }; + 'users/search-by-username-and-host': { req: UsersSearchByUsernameAndHostRequest; res: UsersSearchByUsernameAndHostResponse; errors: UsersSearchByUsernameAndHostErrors }; + 'users/search': { req: UsersSearchRequest; res: UsersSearchResponse; errors: UsersSearchErrors }; + 'users/show': { req: UsersShowRequest; res: UsersShowResponse; errors: UsersShowErrors }; + 'users/achievements': { req: UsersAchievementsRequest; res: UsersAchievementsResponse; errors: UsersAchievementsErrors }; + 'users/update-memo': { req: UsersUpdateMemoRequest; res: EmptyResponse; errors: UsersUpdateMemoErrors }; + 'fetch-rss': { req: FetchRssRequest; res: FetchRssResponse; errors: FetchRssErrors }; + 'fetch-external-resources': { req: FetchExternalResourcesRequest; res: FetchExternalResourcesResponse; errors: FetchExternalResourcesErrors }; + 'retention': { req: EmptyRequest; res: RetentionResponse; errors: RetentionErrors }; + 'bubble-game/register': { req: BubbleGameRegisterRequest; res: EmptyResponse; errors: BubbleGameRegisterErrors }; + 'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse; errors: BubbleGameRankingErrors }; + 'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: EmptyResponse; errors: ReversiCancelMatchErrors }; + 'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse; errors: ReversiGamesErrors }; + 'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse; errors: ReversiMatchErrors }; + 'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse; errors: ReversiInvitationsErrors }; + 'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse; errors: ReversiShowGameErrors }; + 'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse; errors: ReversiSurrenderErrors }; + 'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse; errors: ReversiVerifyErrors }; } diff --git a/packages/misskey-js/src/autogen/endpointErrors.ts b/packages/misskey-js/src/autogen/endpointErrors.ts new file mode 100644 index 0000000000..1631f76d92 --- /dev/null +++ b/packages/misskey-js/src/autogen/endpointErrors.ts @@ -0,0 +1,3052 @@ +/* eslint @typescript-eslint/naming-convention: 0 */ +/* eslint @typescript-eslint/no-explicit-any: 0 */ + +export type EndpointsErrors = { + 'admin___meta': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-user-reports': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-report___notification-recipient___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-report___notification-recipient___show': { + 'NO_SUCH_RECIPIENT': {'message':'No such recipient.', 'code':'NO_SUCH_RECIPIENT', 'id':'013de6a8-f757-04cb-4d73-cc2a7e3368e4', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-report___notification-recipient___create': { + 'CORRELATION_CHECK_EMAIL': {'message':'If "method" is email, "userId" must be set.', 'code':'CORRELATION_CHECK_EMAIL', 'id':'348bb8ae-575a-6fe9-4327-5811999def8f', 'httpStatusCode':400, [x: string]: any }, + 'CORRELATION_CHECK_WEBHOOK': {'message':'If "method" is webhook, "systemWebhookId" must be set.', 'code':'CORRELATION_CHECK_WEBHOOK', 'id':'b0c15051-de2d-29ef-260c-9585cddd701a', 'httpStatusCode':400, [x: string]: any }, + 'EMAIL_ADDRESS_NOT_SET': {'message':'Email address is not set.', 'code':'EMAIL_ADDRESS_NOT_SET', 'id':'7cc1d85e-2f58-fc31-b644-3de8d0d3421f', 'httpStatusCode':400, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-report___notification-recipient___update': { + 'CORRELATION_CHECK_EMAIL': {'message':'If "method" is email, "userId" must be set.', 'code':'CORRELATION_CHECK_EMAIL', 'id':'348bb8ae-575a-6fe9-4327-5811999def8f', 'httpStatusCode':400, [x: string]: any }, + 'CORRELATION_CHECK_WEBHOOK': {'message':'If "method" is webhook, "systemWebhookId" must be set.', 'code':'CORRELATION_CHECK_WEBHOOK', 'id':'b0c15051-de2d-29ef-260c-9585cddd701a', 'httpStatusCode':400, [x: string]: any }, + 'EMAIL_ADDRESS_NOT_SET': {'message':'Email address is not set.', 'code':'EMAIL_ADDRESS_NOT_SET', 'id':'7cc1d85e-2f58-fc31-b644-3de8d0d3421f', 'httpStatusCode':400, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___abuse-report___notification-recipient___delete': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___accounts___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___accounts___delete': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___accounts___find-by-email': { + 'USER_NOT_FOUND': {'message':'No such user who has the email address.', 'code':'USER_NOT_FOUND', 'id':'cb865949-8af5-4062-a88c-ef55e8786d1d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___ad___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___ad___delete': { + 'NO_SUCH_AD': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'ccac9863-3a03-416e-b899-8a64041118b1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___ad___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___ad___update': { + 'NO_SUCH_AD': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'b7aa1727-1354-47bc-a182-3a9c3973d300', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___announcements___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___announcements___delete': { + 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'ecad8040-a276-4e85-bda9-015a708d291e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___announcements___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___announcements___update': { + 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'d3aae5a7-6372-4cb4-b61c-f511ffc2d7cc', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___avatar-decorations___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___avatar-decorations___delete': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___avatar-decorations___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___avatar-decorations___update': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___delete-all-files-of-a-user': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___unset-user-avatar': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___unset-user-banner': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___drive___clean-remote-files': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___drive___cleanup': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___drive___files': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___drive___show-file': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'caf3ca38-c6e5-472e-a30c-b05377dcc240', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___add-aliases-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___add': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'fc46b5a4-6b92-4c33-ac66-b806659bb5cf', [x: string]: any }, + 'DUPLICATE_NAME': {'message':'Duplicate name.', 'code':'DUPLICATE_NAME', 'id':'f7a3462c-4e6e-4069-8421-b9bd4f4c3975', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___copy': { + 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'e2785b66-dca3-4087-9cac-b93c541cc425', [x: string]: any }, + 'DUPLICATE_NAME': {'message':'Duplicate name.', 'code':'DUPLICATE_NAME', 'id':'f7a3462c-4e6e-4069-8421-b9bd4f4c3975', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___delete-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___delete': { + 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'be83669b-773a-44b7-b1f8-e5e5170ac3c2', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___import-zip': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___list-remote': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___remove-aliases-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___set-aliases-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___set-category-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___set-license-bulk': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___emoji___update': { + 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'684dec9d-a8c2-4364-9aa8-456c49cb1dc8', [x: string]: any }, + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'14fb9fd9-0731-4e2f-aeb9-f09e4740333d', [x: string]: any }, + 'SAME_NAME_EMOJI_EXISTS': {'message':'Emoji that have same name already exists.', 'code':'SAME_NAME_EMOJI_EXISTS', 'id':'7180fe9d-1ee3-bff9-647d-fe9896d2ffb8', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___federation___delete-all-files': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___federation___refresh-remote-instance-metadata': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___federation___remove-all-following': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___federation___update-instance': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___get-index-stats': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___get-table-stats': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___get-user-ips': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___invite___create': { + 'INVALID_DATE_TIME': {'message':'Invalid date-time format', 'code':'INVALID_DATE_TIME', 'id':'f1380b15-3760-4c6c-a1db-5c3aaf1cbd49', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___invite___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___promo___create': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ee449fbe-af2a-453b-9cae-cf2fe7c895fc', [x: string]: any }, + 'ALREADY_PROMOTED': {'message':'The note has already promoted.', 'code':'ALREADY_PROMOTED', 'id':'ae427aa2-7a41-484f-a18c-2c1104051604', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___queue___clear': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___queue___deliver-delayed': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___queue___inbox-delayed': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___queue___promote': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___queue___stats': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___relays___add': { + 'INVALID_URL': {'message':'Invalid URL', 'code':'INVALID_URL', 'id':'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___relays___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___relays___remove': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___reset-password': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___resolve-abuse-user-report': { + 'NO_SUCH_ABUSE_REPORT': {'message':'No such abuse report.', 'code':'NO_SUCH_ABUSE_REPORT', 'id':'ac3794dd-2ce4-d878-e546-73c60c06b398', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___send-email': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___server-info': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___show-moderation-logs': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___show-user': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___show-users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___suspend-user': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___unsuspend-user': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___update-meta': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___delete-account': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___update-user-note': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___delete': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de0d6ecd-8e0a-4253-88ff-74bc89ae3d45', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___show': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'07dc7d34-c0d8-49b7-96c6-db3ce64ee0b3', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___update': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'cd23ef55-09ad-428a-ac61-95a45e124b32', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___assign': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6503c040-6af4-4ed9-bf07-f2dd16678eab', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'558ea170-f653-4700-94d0-5a818371d0df', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'25b5bc31-dc79-4ebd-9bd2-c84978fd052c', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___unassign': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6e519036-a70d-4c76-b679-bc8fb18194e2', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'2b730f78-1179-461b-88ad-d24c9af1a5ce', [x: string]: any }, + 'NOT_ASSIGNED': {'message':'Not assigned.', 'code':'NOT_ASSIGNED', 'id':'b9060ac7-5c94-4da4-9f55-2047c953df44', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'24636eee-e8c1-493e-94b2-e16ad401e262', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___update-default-policies': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___roles___users': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'224eff5e-2488-4b18-b3e7-f50d94421648', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___system-webhook___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___system-webhook___delete': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___system-webhook___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___system-webhook___show': { + 'NO_SUCH_SYSTEM_WEBHOOK': {'message':'No such SystemWebhook.', 'code':'NO_SUCH_SYSTEM_WEBHOOK', 'id':'38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'admin___system-webhook___update': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'announcements': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'announcements___show': { + 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'b57b5e1d-4f49-404a-9edb-46b00268f121', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___create': { + 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'95063e93-a283-4b8b-9aa5-bcdb8df69a7f', [x: string]: any }, + 'TOO_MANY_ANTENNAS': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'faf47050-e8b5-438c-913c-db2b1576fde4', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___delete': { + 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'b34dcf9d-348f-44bb-99d0-6c9314cfe2df', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___notes': { + 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'850926e0-fd3b-49b6-b69a-b28a5dbd82fe', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___show': { + 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'c06569fb-b025-4f23-b22d-1fcd20d2816b', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'antennas___update': { + 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'10c673ac-8852-48eb-aa1f-f5b67f069290', [x: string]: any }, + 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'1c6b35c9-943e-48c2-81e4-2844989407f7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'ap___get': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'ap___show': { + 'NO_SUCH_OBJECT': {'message':'No such object.', 'code':'NO_SUCH_OBJECT', 'id':'dc94d745-1262-4e63-a17d-fecaa57efc82', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'app___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'app___show': { + 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'dce83913-2dc6-4093-8a7b-71dbb11718a3', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'auth___accept': { + 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'9c72d8de-391a-43c1-9d06-08d29efde8df', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'auth___session___generate': { + 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'92f93e63-428e-4f2f-a5a4-39e1407fe998', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'auth___session___show': { + 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'bd72c97d-eba7-4adb-a467-f171b8847250', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'auth___session___userkey': { + 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d', [x: string]: any }, + 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3', [x: string]: any }, + 'PENDING_SESSION': {'message':'This session is not completed yet.', 'code':'PENDING_SESSION', 'id':'8c8a4145-02cc-4cca-8e66-29ba60445a8e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'blocking___create': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'7cc4f851-e2f1-4621-9633-ec9e1d00c01e', [x: string]: any }, + 'BLOCKEE_IS_YOURSELF': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'88b19138-f28d-42c0-8499-6a31bbd0fdc6', [x: string]: any }, + 'ALREADY_BLOCKING': {'message':'You are already blocking that user.', 'code':'ALREADY_BLOCKING', 'id':'787fed64-acb9-464a-82eb-afbd745b9614', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'blocking___delete': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'8621d8bf-c358-4303-a066-5ea78610eb3f', [x: string]: any }, + 'BLOCKEE_IS_YOURSELF': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'06f6fac6-524b-473c-a354-e97a40ae6eac', [x: string]: any }, + 'NOT_BLOCKING': {'message':'You are not blocking that user.', 'code':'NOT_BLOCKING', 'id':'291b2efa-60c6-45c0-9f6a-045c8f9b02cd', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'blocking___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___create': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___featured': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___follow': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'c0031718-d573-4e85-928e-10039f1fbb68', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___followed': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___owned': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___show': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'6f6c314b-7486-4897-8966-c04a66a02923', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___timeline': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___unfollow': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'19959ee9-0153-4c51-bbd9-a98c49dc59d6', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___update': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'f9c5467f-d492-4c3c-9a8d-a70dacc86512', [x: string]: any }, + 'ACCESS_DENIED': {'message':'You do not have edit privilege of the channel.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fdf-b8df-057788cce513', [x: string]: any }, + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e86c14a4-0da2-4032-8df3-e737a04c7f3b', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___favorite': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4938f5f3-6167-4c04-9149-6607b7542861', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___unfavorite': { + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'353c68dd-131a-476c-aa99-88a345e83668', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___my-favorites': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'channels___search': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___active-users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___ap-request': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___drive': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___federation': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___instance': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___user___drive': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___user___following': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___user___notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___user___pv': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___user___reactions': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'charts___users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___add-note': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'d6e76cc0-a1b5-4c7c-a287-73fa9c716dcf', [x: string]: any }, + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b', [x: string]: any }, + 'ALREADY_CLIPPED': {'message':'The note has already been clipped.', 'code':'ALREADY_CLIPPED', 'id':'734806c4-542c-463a-9311-15c512803965', [x: string]: any }, + 'TOO_MANY_CLIP_NOTES': {'message':'You cannot add notes to the clip any more.', 'code':'TOO_MANY_CLIP_NOTES', 'id':'f0dba960-ff73-4615-8df4-d6ac5d9dc118', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___remove-note': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b80525c6-97f7-49d7-a42d-ebccd49cfd52', [x: string]: any }, + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'aff017de-190e-434b-893e-33a9ff5049d8', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___create': { + 'TOO_MANY_CLIPS': {'message':'You cannot create clip any more.', 'code':'TOO_MANY_CLIPS', 'id':'920f7c2d-6208-4b76-8082-e632020f5883', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___delete': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'70ca08ba-6865-4630-b6fb-8494759aa754', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___notes': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'1d7645e6-2b6d-4635-b0fe-fe22b0e72e00', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___show': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'c3c5fe33-d62c-44d2-9ea5-d997703f5c20', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___update': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b4d92d70-b216-46fa-9a3f-a8c811699257', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___favorite': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'4c2aaeae-80d8-4250-9606-26cb1fdb77a5', [x: string]: any }, + 'ALREADY_FAVORITED': {'message':'The clip has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'92658936-c625-4273-8326-2d790129256e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___unfavorite': { + 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'2603966e-b865-426c-94a7-af4a01241dc1', [x: string]: any }, + 'NOT_FAVORITED': {'message':'You have not favorited the clip.', 'code':'NOT_FAVORITED', 'id':'90c3a9e8-b321-4dae-bf57-2bf79bbcc187', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'clips___my-favorites': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___attached-notes': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'c118ece3-2e4b-4296-99d1-51756e32d232', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___check-existence': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___create': { + 'INVALID_FILE_NAME': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'f449b209-0c60-4e51-84d5-29486263bfd4', [x: string]: any }, + 'INAPPROPRIATE': {'message':'Cannot upload the file because it has been determined that it possibly contains inappropriate content.', 'code':'INAPPROPRIATE', 'id':'bec5bd69-fba3-43c9-b4fb-2894b66ad5d2', [x: string]: any }, + 'NO_FREE_SPACE': {'message':'Cannot upload the file because you have no free space of drive.', 'code':'NO_FREE_SPACE', 'id':'d08dbc37-a6a9-463a-8c47-96c32ab5f064', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___delete': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'908939ec-e52b-4458-b395-1025195cea58', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'5eb8d909-2540-4970-90b8-dd6f86088121', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___find-by-hash': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___find': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___show': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'067bc436-2718-4795-b0fb-ecbe43949e31', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'25b73c73-68b1-41d0-bad1-381cfdf6579f', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___update': { + 'INVALID_FILE_NAME': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'395e7156-f9f0-475e-af89-53c3c23080c2', [x: string]: any }, + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e7778c7e-3af9-49cd-9690-6dbc3e6c972d', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'01a53b27-82fc-445b-a0c1-b558465a8ed2', [x: string]: any }, + 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'ea8fb7a5-af77-4a08-b608-c0218176cd73', [x: string]: any }, + 'RESTRICTED_BY_ROLE': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'7f59dccb-f465-75ab-5cf4-3ce44e3282f7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___files___upload-from-url': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders___create': { + 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'53326628-a00d-40a6-a3cd-8975105c0f95', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders___delete': { + 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'1069098f-c281-440f-b085-f9932edbe091', [x: string]: any }, + 'HAS_CHILD_FILES_OR_FOLDERS': {'message':'This folder has child files or folders.', 'code':'HAS_CHILD_FILES_OR_FOLDERS', 'id':'b0fc8a17-963c-405d-bfbc-859a487295e1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders___find': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders___show': { + 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'d74ab9eb-bb09-4bba-bf24-fb58f761e1e9', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___folders___update': { + 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'f7974dac-2c0d-4a27-926e-23583b28e98e', [x: string]: any }, + 'NO_SUCH_PARENT_FOLDER': {'message':'No such parent folder.', 'code':'NO_SUCH_PARENT_FOLDER', 'id':'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1', [x: string]: any }, + 'RECURSIVE_NESTING': {'message':'It can not be structured like nesting folders recursively.', 'code':'RECURSIVE_NESTING', 'id':'dbeb024837894013aed44279f9199740', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'drive___stream': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'email-address___available': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'endpoint': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'endpoints': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'export-custom-emojis': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___followers': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___following': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___instances': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___show-instance': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___update-remote-user': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'federation___stats': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___create': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, + 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'26fbe7bb-a331-4857-af17-205b426669a9', [x: string]: any }, + 'ALREADY_FOLLOWING': {'message':'You are already following that user.', 'code':'ALREADY_FOLLOWING', 'id':'35387507-38c7-4cb9-9197-300b93783fa0', [x: string]: any }, + 'BLOCKING': {'message':'You are blocking that user.', 'code':'BLOCKING', 'id':'4e2206ec-aa4f-4960-b865-6c23ac38e2d9', [x: string]: any }, + 'BLOCKED': {'message':'You are blocked by that user.', 'code':'BLOCKED', 'id':'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___delete': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5b12c78d-2b28-4dca-99d2-f56139b42ff8', [x: string]: any }, + 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'d9e400b9-36b0-4808-b1d8-79e707f1296c', [x: string]: any }, + 'NOT_FOLLOWING': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___update': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'14318698-f67e-492a-99da-5353a5ac52be', [x: string]: any }, + 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'4c4cbaf9-962a-463b-8418-a5e365dbf2eb', [x: string]: any }, + 'NOT_FOLLOWING': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___update-all': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___invalidate': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b77e6ae6-a3e5-40da-9cc8-c240115479cc', [x: string]: any }, + 'FOLLOWER_IS_YOURSELF': {'message':'Follower is yourself.', 'code':'FOLLOWER_IS_YOURSELF', 'id':'07dc03b9-03da-422d-885b-438313707662', [x: string]: any }, + 'NOT_FOLLOWING': {'message':'The other use is not following you.', 'code':'NOT_FOLLOWING', 'id':'918faac3-074f-41ae-9c43-ed5d2946770d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___requests___accept': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'66ce1645-d66c-46bb-8b79-96739af885bd', [x: string]: any }, + 'NO_FOLLOW_REQUEST': {'message':'No follow request.', 'code':'NO_FOLLOW_REQUEST', 'id':'bcde4f8b-0913-4614-8881-614e522fb041', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___requests___cancel': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4e68c551-fc4c-4e46-bb41-7d4a37bf9dab', [x: string]: any }, + 'FOLLOW_REQUEST_NOT_FOUND': {'message':'Follow request not found.', 'code':'FOLLOW_REQUEST_NOT_FOUND', 'id':'089b125b-d338-482a-9a09-e2622ac9f8d4', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___requests___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'following___requests___reject': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'abc2ffa6-25b2-4380-ba99-321ff3a94555', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___featured': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___popular': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___delete': { + 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'ae52f367-4bd7-4ecd-afc6-5672fff427f5', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___like': { + 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'56c06af3-1287-442f-9701-c93f7c4a62ff', [x: string]: any }, + 'YOUR_POST': {'message':'You cannot like your post.', 'code':'YOUR_POST', 'id':'f78f1511-5ebc-4478-a888-1198d752da68', [x: string]: any }, + 'ALREADY_LIKED': {'message':'The post has already been liked.', 'code':'ALREADY_LIKED', 'id':'40e9ed56-a59c-473a-bf3f-f289c54fb5a7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___show': { + 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'1137bf14-c5b0-4604-85bb-5b5371b1cd45', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___unlike': { + 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'c32e6dd0-b555-4413-925e-b3757d19ed84', [x: string]: any }, + 'NOT_LIKED': {'message':'You have not liked that post.', 'code':'NOT_LIKED', 'id':'e3e8e06e-be37-41f7-a5b4-87a8250288f0', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'gallery___posts___update': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'get-online-users-count': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'get-avatar-decorations': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'hashtags___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'hashtags___search': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'hashtags___show': { + 'NO_SUCH_HASHTAG': {'message':'No such hashtag.', 'code':'NO_SUCH_HASHTAG', 'id':'110ee688-193e-4a3a-9ecf-c167b2e6981e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'hashtags___trend': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'hashtags___users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i': { + 'USER_IS_DELETED': {'message':'User is deleted.', 'code':'USER_IS_DELETED', 'id':'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a', 'kind':'permission', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___done': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___key-done': { + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'0d7ec6d2-e652-443e-a7bf-9ee9a0cd77b0', [x: string]: any }, + 'TWO_FACTOR_NOT_ENABLED': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'798d6847-b1ed-4f9c-b1f9-163c42655995', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___password-less': { + 'NO_SECURITY_KEY': {'message':'No security key.', 'code':'NO_SECURITY_KEY', 'id':'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___register-key': { + 'USER_NOT_FOUND': {'message':'User not found.', 'code':'USER_NOT_FOUND', 'id':'652f899f-66d4-490e-993e-6606c8ec04c3', [x: string]: any }, + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'38769596-efe2-4faf-9bec-abbb3f2cd9ba', [x: string]: any }, + 'TWO_FACTOR_NOT_ENABLED': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'bf32b864-449b-47b8-974e-f9a5468546f1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___register': { + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'78d6c839-20c9-4c66-b90a-fc0542168b48', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___update-key': { + 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'f9c5467f-d492-4d3c-9a8g-a70dacc86512', [x: string]: any }, + 'ACCESS_DENIED': {'message':'You do not have edit privilege of this key.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fff-b8df-057708cce513', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___remove-key': { + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'141c598d-a825-44c8-9173-cfb9d92be493', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___2fa___unregister': { + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'7add0395-9901-4098-82f9-4f67af65f775', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___apps': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___authorized-apps': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___claim-achievement': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___change-password': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___delete-account': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-blocking': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-following': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-mute': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-clips': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-favorites': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-user-lists': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___export-antennas': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___favorites': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___gallery___likes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___gallery___posts': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___import-blocking': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e', [x: string]: any }, + 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe', [x: string]: any }, + 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf', [x: string]: any }, + 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'6f3a4dcc-f060-a707-4950-806fbdbe60d6', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___import-following': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b98644cf-a5ac-4277-a502-0b8054a709a3', [x: string]: any }, + 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'660f3599-bce0-4f95-9dde-311fd841c183', [x: string]: any }, + 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'dee9d4ed-ad07-43ed-8b34-b2856398bc60', [x: string]: any }, + 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'31a1b42c-06f7-42ae-8a38-a661c5c9f691', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___import-muting': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e674141e-bd2a-ba85-e616-aefb187c9c2a', [x: string]: any }, + 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'568c6e42-c86c-ba09-c004-517f83f9f1a8', [x: string]: any }, + 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'9b4ada6d-d7f7-0472-0713-4f558bd1ec9c', [x: string]: any }, + 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'d2f12af1-e7b4-feac-86a3-519548f2728e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___import-user-lists': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ea9cc34f-c415-4bc6-a6fe-28ac40357049', [x: string]: any }, + 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'a3c9edda-dd9b-4596-be6a-150ef813745c', [x: string]: any }, + 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9', [x: string]: any }, + 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'99efe367-ce6e-4d44-93f8-5fae7b040356', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___import-antennas': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'3b71d086-c3fa-431c-b01d-ded65a777172', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e842c379-8ac7-4cf7-b07a-4d4de7e4671c', [x: string]: any }, + 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'7f60115d-8d93-4b0f-bd0e-3815dcbb389f', [x: string]: any }, + 'TOO_MANY_ANTENNAS': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'600917d4-a4cb-4cc5-8ba8-7ac8ea3c7779', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___notifications': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___notifications-grouped': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___page-likes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___pages': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___pin': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'56734f8b-3928-431e-bf80-6ff87df40cb3', [x: string]: any }, + 'PIN_LIMIT_EXCEEDED': {'message':'You can not pin notes any more.', 'code':'PIN_LIMIT_EXCEEDED', 'id':'72dab508-c64d-498f-8740-a8eec1ba385a', [x: string]: any }, + 'ALREADY_PINNED': {'message':'That note has already been pinned.', 'code':'ALREADY_PINNED', 'id':'8b18c2b7-68fe-4edb-9892-c0cbaeb6c913', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___read-all-unread-notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___read-announcement': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___regenerate-token': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___get-all': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___get-detail': { + 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'97a1e8e7-c0f7-47d2-957a-92e61256e01a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___get': { + 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___keys-with-type': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___keys': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___remove': { + 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___scopes-with-domain': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___registry___set': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___revoke-token': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___signin-history': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___unpin': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'454170ce-9d63-4a43-9da1-ea10afe81e21', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___update-email': { + 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3', [x: string]: any }, + 'UNAVAILABLE': {'message':'Unavailable email address.', 'code':'UNAVAILABLE', 'id':'a2defefb-f220-8849-0af6-17f816099323', [x: string]: any }, + 'EMAIL_REQUIRED': {'message':'Email address is required.', 'code':'EMAIL_REQUIRED', 'id':'324c7a88-59f2-492f-903f-89134f93e47e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___update': { + 'NO_SUCH_AVATAR': {'message':'No such avatar file.', 'code':'NO_SUCH_AVATAR', 'id':'539f3a45-f215-4f81-a9a8-31293640207f', [x: string]: any }, + 'NO_SUCH_BANNER': {'message':'No such banner file.', 'code':'NO_SUCH_BANNER', 'id':'0d8f5629-f210-41c2-9433-735831a58595', [x: string]: any }, + 'AVATAR_NOT_AN_IMAGE': {'message':'The file specified as an avatar is not an image.', 'code':'AVATAR_NOT_AN_IMAGE', 'id':'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191', [x: string]: any }, + 'BANNER_NOT_AN_IMAGE': {'message':'The file specified as a banner is not an image.', 'code':'BANNER_NOT_AN_IMAGE', 'id':'75aedb19-2afd-4e6d-87fc-67941256fa60', [x: string]: any }, + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'8e01b590-7eb9-431b-a239-860e086c408e', [x: string]: any }, + 'INVALID_REGEXP': {'message':'Invalid Regular Expression.', 'code':'INVALID_REGEXP', 'id':'0d786918-10df-41cd-8f33-8dec7d9a89a5', [x: string]: any }, + 'TOO_MANY_MUTED_WORDS': {'message':'Too many muted words.', 'code':'TOO_MANY_MUTED_WORDS', 'id':'010665b1-a211-42d2-bc64-8f6609d79785', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, + 'URI_NULL': {'message':'User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'bf326f31-d430-4f97-9933-5d61e4d48a23', [x: string]: any }, + 'FORBIDDEN_TO_SET_YOURSELF': {'message':'You can\'t set yourself as your own alias.', 'code':'FORBIDDEN_TO_SET_YOURSELF', 'id':'25c90186-4ab0-49c8-9bba-a1fa6c202ba4', [x: string]: any }, + 'RESTRICTED_BY_ROLE': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'8feff0ba-5ab5-585b-31f4-4df816663fad', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___move': { + 'DESTINATION_ACCOUNT_FORBIDS': {'message':'Destination account doesn\'t have proper \'Known As\' alias, or has already moved.', 'code':'DESTINATION_ACCOUNT_FORBIDS', 'id':'b5c90186-4ab0-49c8-9bba-a1f766282ba4', [x: string]: any }, + 'NOT_ROOT_FORBIDDEN': {'message':'The root can\'t migrate.', 'code':'NOT_ROOT_FORBIDDEN', 'id':'4362e8dc-731f-4ad8-a694-be2a88922a24', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, + 'URI_NULL': {'message':'Local User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'95ba11b9-90e8-43a5-ba16-7acc1ab32e71', [x: string]: any }, + 'ALREADY_MOVED': {'message':'Account was already moved to another account.', 'code':'ALREADY_MOVED', 'id':'b234a14e-9ebe-4581-8000-074b3c215962', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___webhooks___create': { + 'TOO_MANY_WEBHOOKS': {'message':'You cannot create webhook any more.', 'code':'TOO_MANY_WEBHOOKS', 'id':'87a9bb19-111e-4e37-81d3-a3e7426453b0', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___webhooks___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___webhooks___show': { + 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'50f614d9-3047-4f7e-90d8-ad6b2d5fb098', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___webhooks___update': { + 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'fb0fea69-da18-45b1-828d-bd4fd1612518', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'i___webhooks___delete': { + 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'bae73e5a-5522-4965-ae19-3a8688e71d82', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'invite___create': { + 'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE': {'message':'You have exceeded the limit for creating an invitation code.', 'code':'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE', 'id':'8b165dd3-6f37-4557-8db1-73175d63c641', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'invite___delete': { + 'NO_SUCH_INVITE_CODE': {'message':'No such invite code.', 'code':'NO_SUCH_INVITE_CODE', 'id':'cd4f9ae4-7854-4e3e-8df9-c296f051e634', [x: string]: any }, + 'CAN_NOT_DELETE_INVITE_CODE': {'message':'You can\'t delete this invite code.', 'code':'CAN_NOT_DELETE_INVITE_CODE', 'id':'ff17af39-000c-4d4e-abdf-848fa30fc1ce', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'5eb8d909-2540-4970-90b8-dd6f86088121', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'invite___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'invite___limit': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'meta': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'emojis': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'emoji': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'miauth___gen-token': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'mute___create': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'6fef56f3-e765-4957-88e5-c6f65329b8a5', [x: string]: any }, + 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'a4619cb2-5f23-484b-9301-94c903074e10', [x: string]: any }, + 'ALREADY_MUTING': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'7e7359cb-160c-4956-b08f-4d1c653cd007', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'mute___delete': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b851d00b-8ab1-4a56-8b1b-e24187cb48ef', [x: string]: any }, + 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9', [x: string]: any }, + 'NOT_MUTING': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'5467d020-daa9-4553-81e1-135c0c35a96d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'mute___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'renote-mute___create': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5e0a5dff-1e94-4202-87ae-4d9c89eb2271', [x: string]: any }, + 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'37285718-52f7-4aef-b7de-c38b8e8a8420', [x: string]: any }, + 'ALREADY_MUTING': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'ccfecbe4-1f1c-4fc2-8a3d-c3ffee61cb7b', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'renote-mute___delete': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'9b6728cf-638c-4aa1-bedb-e07d8101474d', [x: string]: any }, + 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'619b1314-0850-4597-a242-e245f3da42af', [x: string]: any }, + 'NOT_MUTING': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'2e4ef874-8bf0-4b4b-b069-4598f6d05817', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'renote-mute___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'my___apps': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___children': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___clips': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'47db1a1c-b0af-458d-8fb4-986e4efafe1e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___conversation': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'e1035875-9551-45ec-afa8-1ded1fcb53c8', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___create': { + 'NO_SUCH_RENOTE_TARGET': {'message':'No such renote target.', 'code':'NO_SUCH_RENOTE_TARGET', 'id':'b5c90186-4ab0-49c8-9bba-a1f76c282ba4', [x: string]: any }, + 'CANNOT_RENOTE_TO_A_PURE_RENOTE': {'message':'You can not Renote a pure Renote.', 'code':'CANNOT_RENOTE_TO_A_PURE_RENOTE', 'id':'fd4cc33e-2a37-48dd-99cc-9b806eb2031a', [x: string]: any }, + 'CANNOT_RENOTE_DUE_TO_VISIBILITY': {'message':'You can not Renote due to target visibility.', 'code':'CANNOT_RENOTE_DUE_TO_VISIBILITY', 'id':'be9529e9-fe72-4de0-ae43-0b363c4938af', [x: string]: any }, + 'NO_SUCH_REPLY_TARGET': {'message':'No such reply target.', 'code':'NO_SUCH_REPLY_TARGET', 'id':'749ee0f6-d3da-459a-bf02-282e2da4292c', [x: string]: any }, + 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE': {'message':'You cannot reply to an invisible Note.', 'code':'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE', 'id':'b98980fa-3780-406c-a935-b6d0eeee10d1', [x: string]: any }, + 'CANNOT_REPLY_TO_A_PURE_RENOTE': {'message':'You can not reply to a pure Renote.', 'code':'CANNOT_REPLY_TO_A_PURE_RENOTE', 'id':'3ac74a84-8fd5-4bb0-870f-01804f82ce15', [x: string]: any }, + 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY': {'message':'You cannot reply to a specified visibility note with extended visibility.', 'code':'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY', 'id':'ed940410-535c-4d5e-bfa3-af798671e93c', [x: string]: any }, + 'CANNOT_CREATE_ALREADY_EXPIRED_POLL': {'message':'Poll is already expired.', 'code':'CANNOT_CREATE_ALREADY_EXPIRED_POLL', 'id':'04da457d-b083-4055-9082-955525eda5a5', [x: string]: any }, + 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'b1653923-5453-4edc-b786-7c4f39bb0bbb', [x: string]: any }, + 'YOU_HAVE_BEEN_BLOCKED': {'message':'You have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'b390d7e1-8a5e-46ed-b625-06271cafd3d3', [x: string]: any }, + 'NO_SUCH_FILE': {'message':'Some files are not found.', 'code':'NO_SUCH_FILE', 'id':'b6992544-63e7-67f0-fa7f-32444b1b5306', [x: string]: any }, + 'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL': {'message':'Cannot renote outside of channel.', 'code':'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL', 'id':'33510210-8452-094c-6227-4a6c05d99f00', [x: string]: any }, + 'CONTAINS_PROHIBITED_WORDS': {'message':'Cannot post because it contains prohibited words.', 'code':'CONTAINS_PROHIBITED_WORDS', 'id':'aa6e01d3-a85c-669d-758a-76aab43af334', [x: string]: any }, + 'CONTAINS_TOO_MANY_MENTIONS': {'message':'Cannot post because it exceeds the allowed number of mentions.', 'code':'CONTAINS_TOO_MANY_MENTIONS', 'id':'4de0363a-3046-481b-9b0f-feff3e211025', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___delete': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'490be23f-8c1f-4796-819f-94cb4f9d1630', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___favorites___create': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'6dd26674-e060-4816-909a-45ba3f4da458', [x: string]: any }, + 'ALREADY_FAVORITED': {'message':'The note has already been marked as a favorite.', 'code':'ALREADY_FAVORITED', 'id':'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___favorites___delete': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'80848a2c-398f-4343-baa9-df1d57696c56', [x: string]: any }, + 'NOT_FAVORITED': {'message':'You have not marked that note a favorite.', 'code':'NOT_FAVORITED', 'id':'b625fc69-635e-45e9-86f4-dbefbef35af5', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___featured': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___global-timeline': { + 'GTL_DISABLED': {'message':'Global timeline has been disabled.', 'code':'GTL_DISABLED', 'id':'0332fc13-6ab2-4427-ae80-a9fadffd1a6b', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___hybrid-timeline': { + 'STL_DISABLED': {'message':'Hybrid timeline has been disabled.', 'code':'STL_DISABLED', 'id':'620763f4-f621-4533-ab33-0577a1a3c342', [x: string]: any }, + 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dfaa3eb7-8002-4cb7-bcc4-1095df46656f', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___local-timeline': { + 'LTL_DISABLED': {'message':'Local timeline has been disabled.', 'code':'LTL_DISABLED', 'id':'45a6eb02-7695-4393-b023-dd3be9aaaefd', [x: string]: any }, + 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dd9c8400-1cb5-4eef-8a31-200c5f933793', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___mentions': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___polls___recommendation': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___polls___vote': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ecafbd2e-c283-4d6d-aecb-1a0a33b75396', [x: string]: any }, + 'NO_POLL': {'message':'The note does not attach a poll.', 'code':'NO_POLL', 'id':'5f979967-52d9-4314-a911-1c673727f92f', [x: string]: any }, + 'INVALID_CHOICE': {'message':'Choice ID is invalid.', 'code':'INVALID_CHOICE', 'id':'e0cc9a04-f2e8-41e4-a5f1-4127293260cc', [x: string]: any }, + 'ALREADY_VOTED': {'message':'You have already voted.', 'code':'ALREADY_VOTED', 'id':'0963fc77-efac-419b-9424-b391608dc6d8', [x: string]: any }, + 'ALREADY_EXPIRED': {'message':'The poll is already expired.', 'code':'ALREADY_EXPIRED', 'id':'1022a357-b085-4054-9083-8f8de358337e', [x: string]: any }, + 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot vote this poll because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'85a5377e-b1e9-4617-b0b9-5bea73331e49', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___reactions': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'263fff3d-d0e1-4af4-bea7-8408059b451a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___reactions___create': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'033d0620-5bfe-4027-965d-980b0c85a3ea', [x: string]: any }, + 'ALREADY_REACTED': {'message':'You are already reacting to that note.', 'code':'ALREADY_REACTED', 'id':'71efcf98-86d6-4e2b-b2ad-9d032369366b', [x: string]: any }, + 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot react this note because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'20ef5475-9f38-4e4c-bd33-de6d979498ec', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___reactions___delete': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37', [x: string]: any }, + 'NOT_REACTED': {'message':'You are not reacting to that note.', 'code':'NOT_REACTED', 'id':'92f4426d-4196-4125-aa5b-02943e2ec8fc', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___renotes': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'12908022-2e21-46cd-ba6a-3edaf6093f46', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___replies': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___search-by-tag': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___search': { + 'UNAVAILABLE': {'message':'Search of notes unavailable.', 'code':'UNAVAILABLE', 'id':'0b44998d-77aa-4427-80d0-d2c9b8523011', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___show': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'24fcbfc6-2e37-42b6-8388-c29b3861a08d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___state': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___thread-muting___create': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'5ff67ada-ed3b-2e71-8e87-a1a421e177d2', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___thread-muting___delete': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bddd57ac-ceb3-b29d-4334-86ea5fae481a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___timeline': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___translate': { + 'UNAVAILABLE': {'message':'Translate of notes unavailable.', 'code':'UNAVAILABLE', 'id':'50a70314-2d8a-431b-b433-efa5cc56444c', [x: string]: any }, + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bea9b03f-36e0-49c5-a4db-627a029f8971', [x: string]: any }, + 'CANNOT_TRANSLATE_INVISIBLE_NOTE': {'message':'Cannot translate invisible note.', 'code':'CANNOT_TRANSLATE_INVISIBLE_NOTE', 'id':'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___unrenote': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'efd4a259-2442-496b-8dd7-b255aa1a160f', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notes___user-list-timeline': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notifications___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notifications___flush': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notifications___mark-all-as-read': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'notifications___test-notification': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'page-push': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'4a13ad31-6729-46b4-b9af-e86b265c2e74', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___create': { + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c', [x: string]: any }, + 'NAME_ALREADY_EXISTS': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'4650348e-301c-499a-83c9-6aa988c66bc1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___delete': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'eb0c6e1d-d519-4764-9486-52a7e1c6392a', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'8b741b3e-2c22-44b3-a15f-29949aa1601e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___featured': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___like': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'cc98a8a2-0dc3-4123-b198-62c71df18ed3', [x: string]: any }, + 'YOUR_PAGE': {'message':'You cannot like your page.', 'code':'YOUR_PAGE', 'id':'28800466-e6db-40f2-8fae-bf9e82aa92b8', [x: string]: any }, + 'ALREADY_LIKED': {'message':'The page has already been liked.', 'code':'ALREADY_LIKED', 'id':'d4c1edbe-7da2-4eae-8714-1acfd2d63941', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___show': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'222120c0-3ead-4528-811b-b96f233388d7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___unlike': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'a0d41e20-1993-40bd-890e-f6e560ae648e', [x: string]: any }, + 'NOT_LIKED': {'message':'You have not liked that page.', 'code':'NOT_LIKED', 'id':'f5e586b0-ce93-4050-b0e3-7f31af5259ee', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pages___update': { + 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'21149b9e-3616-4778-9592-c4ce89f5a864', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'3c15cd52-3b4b-4274-967d-6456fc4f792b', [x: string]: any }, + 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cfc23c7c-3887-490e-af30-0ed576703c82', [x: string]: any }, + 'NAME_ALREADY_EXISTS': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___create': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___delete': { + 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'de1623ef-bbb3-4289-a71e-14cfa83d9740', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'1036ad7b-9f92-4fff-89c3-0e50dc941704', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___featured': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___like': { + 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'c07c1491-9161-4c5c-9d75-01906f911f73', [x: string]: any }, + 'YOUR_FLASH': {'message':'You cannot like your flash.', 'code':'YOUR_FLASH', 'id':'3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b', [x: string]: any }, + 'ALREADY_LIKED': {'message':'The flash has already been liked.', 'code':'ALREADY_LIKED', 'id':'010065cf-ad43-40df-8067-abff9f4686e3', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___show': { + 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'f0d34a1a-d29a-401d-90ba-1982122b5630', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___unlike': { + 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'afe8424a-a69e-432d-a5f2-2f0740c62410', [x: string]: any }, + 'NOT_LIKED': {'message':'You have not liked that flash.', 'code':'NOT_LIKED', 'id':'755f25a7-9871-4f65-9f34-51eaad9ae0ac', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___update': { + 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'611e13d2-309e-419a-a5e4-e0422da39b02', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'08e60c88-5948-478e-a132-02ec701d67b2', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___my': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'flash___my-likes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'ping': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'pinned-users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'promo___read': { + 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'d785b897-fcd3-4fe9-8fc3-b85c26e6c932', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'roles___list': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'roles___show': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de5502bf-009a-4639-86c1-fec349e46dcb', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'roles___users': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'30aaaee3-4792-48dc-ab0d-cf501a575ac5', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'roles___notes': { + 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'eb70323a-df61-4dd4-ad90-89c83c7cf26e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'request-reset-password': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reset-db': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reset-password': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'server-info': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'stats': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'sw___show-registration': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'sw___update-registration': { + 'NO_SUCH_REGISTRATION': {'message':'No such registration.', 'code':'NO_SUCH_REGISTRATION', 'id':' b09d8066-8064-5613-efb6-0e963b21d012', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'sw___register': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'sw___unregister': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'test': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'username___available': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___clips': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___followers': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27fa5435-88ab-43de-9360-387de88727cd', [x: string]: any }, + 'FORBIDDEN': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'3c6a84db-d619-26af-ca14-06232a21df8a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___following': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'63e4aba4-4156-4e53-be25-c9559e42d71b', [x: string]: any }, + 'FORBIDDEN': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', [x: string]: any }, + 'BIRTHDAY_DATE_FORMAT_INVALID': {'message':'Birthday date format is invalid.', 'code':'BIRTHDAY_DATE_FORMAT_INVALID', 'id':'a2b007b9-4782-4eba-abd3-93b05ed4130d', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___gallery___posts': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___get-frequently-replied-users': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e6965129-7b2a-40a4-bae2-cd84cd434822', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___featured-notes': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___create': { + 'TOO_MANY_USERLISTS': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'0cf21a28-7715-4f39-a20d-777bfdb8d138', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___delete': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'78436795-db79-42f5-b1e2-55ea2cf19166', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___list': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a8af4a82-0980-4cc4-a6af-8b0ffd54465e', [x: string]: any }, + 'REMOTE_USER_NOT_ALLOWED': {'message':'Not allowed to load the remote user\'s list', 'code':'REMOTE_USER_NOT_ALLOWED', 'id':'53858f1b-3315-4a01-81b7-db9b48d4b79a', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___pull': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'588e7f72-c744-4a61-b180-d354e912bda2', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___push': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'2214501d-ac96-4049-b717-91e42272a711', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a', [x: string]: any }, + 'ALREADY_ADDED': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'1de7c884-1595-49e9-857e-61f12f4d4fc5', [x: string]: any }, + 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'990232c5-3f9d-4d83-9f3f-ef27b6332a4b', [x: string]: any }, + 'TOO_MANY_USERS': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'2dd9752e-a338-413d-8eec-41814430989b', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___show': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7bc05c21-1d7a-41ae-88f1-66820f4dc686', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___favorite': { + 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'7dbaf3cf-7b42-4b8f-b431-b3919e580dbe', [x: string]: any }, + 'ALREADY_FAVORITED': {'message':'The list has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'6425bba0-985b-461e-af1b-518070e72081', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___unfavorite': { + 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'baedb33e-76b8-4b0c-86a8-9375c0a7b94b', [x: string]: any }, + 'ALREADY_FAVORITED': {'message':'You have not favorited the list.', 'code':'ALREADY_FAVORITED', 'id':'835c4b27-463d-4cfa-969b-a9058678d465', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___update': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'796666fe-3dff-4d39-becb-8a5932c1d5b7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___create-from-public': { + 'TOO_MANY_USERLISTS': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'e9c105b2-c595-47de-97fb-7f7c2c33e92f', [x: string]: any }, + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'9292f798-6175-4f7d-93f4-b6742279667d', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'13c457db-a8cb-4d88-b70a-211ceeeabb5f', [x: string]: any }, + 'ALREADY_ADDED': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'c3ad6fdb-692b-47ee-a455-7bd12c7af615', [x: string]: any }, + 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'a2497f2a-2389-439c-8626-5298540530f4', [x: string]: any }, + 'TOO_MANY_USERS': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'1845ea77-38d1-426e-8e4e-8b83b24f5bd7', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___update-membership': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'588e7f72-c744-4a61-b180-d354e912bda2', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___lists___get-memberships': { + 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7bc05c21-1d7a-41ae-88f1-66820f4dc686', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___notes': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27e494ba-2ac2-48e8-893b-10d4d8c2387b', [x: string]: any }, + 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'91c8cb9f-36ed-46e7-9ca2-7df96ed6e222', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___pages': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___flashs': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___reactions': { + 'REACTIONS_NOT_PUBLIC': {'message':'Reactions of the user is not public.', 'code':'REACTIONS_NOT_PUBLIC', 'id':'673a7dd2-6924-1093-e0c0-e68456ceae5c', [x: string]: any }, + 'IS_REMOTE_USER': {'message':'Currently unavailable to display reactions of remote users. See https://github.com/misskey-dev/misskey/issues/12964', 'code':'IS_REMOTE_USER', 'id':'6b95fa98-8cf9-2350-e284-f0ffdb54a805', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___recommendation': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___relation': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___report-abuse': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'1acefcb5-0959-43fd-9685-b48305736cb5', [x: string]: any }, + 'CANNOT_REPORT_YOURSELF': {'message':'Cannot report yourself.', 'code':'CANNOT_REPORT_YOURSELF', 'id':'1e13149e-b1e8-43cf-902e-c01dbfcb202f', [x: string]: any }, + 'CANNOT_REPORT_THE_ADMIN': {'message':'Cannot report the admin.', 'code':'CANNOT_REPORT_THE_ADMIN', 'id':'35e166f5-05fb-4f87-a2d5-adb42676d48f', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___search-by-username-and-host': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___search': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___show': { + 'FAILED_TO_RESOLVE_REMOTE_USER': {'message':'Failed to resolve remote user.', 'code':'FAILED_TO_RESOLVE_REMOTE_USER', 'id':'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c', 'kind':'server', [x: string]: any }, + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4362f8dc-731f-4ad8-a694-be5a88922a24', 'httpStatusCode':404, [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___achievements': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'users___update-memo': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'6fef56f3-e765-4957-88e5-c6f65329b8a5', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'fetch-rss': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'fetch-external-resources': { + 'EXT_RESOURCE_RETURNED_INVALID_SCHEMA': {'message':'External resource returned invalid schema.', 'code':'EXT_RESOURCE_RETURNED_INVALID_SCHEMA', 'id':'bb774091-7a15-4a70-9dc5-6ac8cf125856', [x: string]: any }, + 'EXT_RESOURCE_HASH_DIDNT_MATCH': {'message':'Hash did not match.', 'code':'EXT_RESOURCE_HASH_DIDNT_MATCH', 'id':'693ba8ba-b486-40df-a174-72f8279b56a4', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'retention': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'bubble-game___register': { + 'INVALID_SEED': {'message':'Provided seed is invalid.', 'code':'INVALID_SEED', 'id':'eb627bc7-574b-4a52-a860-3c3eae772b88', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'bubble-game___ranking': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___cancel-match': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___games': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___match': { + 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'0b4f0559-b484-4e31-9581-3f73cee89b28', [x: string]: any }, + 'TARGET_IS_YOURSELF': {'message':'Target user is yourself.', 'code':'TARGET_IS_YOURSELF', 'id':'96fd7bd6-d2bc-426c-a865-d055dcd2828e', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___invitations': { + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___show-game': { + 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'f13a03db-fae1-46c9-87f3-43c8165419e1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___surrender': { + 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'ace0b11f-e0a6-4076-a30d-e8284c81b2df', [x: string]: any }, + 'ALREADY_ENDED': {'message':'That game has already ended.', 'code':'ALREADY_ENDED', 'id':'6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d', [x: string]: any }, + 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'6e04164b-a992-4c93-8489-2123069973e1', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, + 'reversi___verify': { + 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'8fb05624-b525-43dd-90f7-511852bdfeee', [x: string]: any }, + 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + }, +}; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index 357b5e9eaf..292cf1076c 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -1,576 +1,957 @@ /* eslint @typescript-eslint/naming-convention: 0 */ import { operations } from './types.js'; +import { EndpointsErrors as _Operations_EndpointsErrors } from './endpointErrors.js'; export type EmptyRequest = Record | undefined; export type EmptyResponse = Record | undefined; +export type EmptyErrors = Record | undefined; export type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json']; +export type AdminMetaErrors = _Operations_EndpointsErrors['admin___meta'][keyof _Operations_EndpointsErrors['admin___meta']]; export type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; export type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json']; +export type AdminAbuseUserReportsErrors = _Operations_EndpointsErrors['admin___abuse-user-reports'][keyof _Operations_EndpointsErrors['admin___abuse-user-reports']]; export type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientListErrors = _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___list'][keyof _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___list']]; export type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientShowErrors = _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___show'][keyof _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___show']]; export type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientCreateErrors = _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___create'][keyof _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___create']]; export type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientUpdateErrors = _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___update'][keyof _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___update']]; export type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientDeleteErrors = _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___delete'][keyof _Operations_EndpointsErrors['admin___abuse-report___notification-recipient___delete']]; export type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json']; export type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json']; +export type AdminAccountsCreateErrors = _Operations_EndpointsErrors['admin___accounts___create'][keyof _Operations_EndpointsErrors['admin___accounts___create']]; export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; +export type AdminAccountsDeleteErrors = _Operations_EndpointsErrors['admin___accounts___delete'][keyof _Operations_EndpointsErrors['admin___accounts___delete']]; export type AdminAccountsFindByEmailRequest = operations['admin___accounts___find-by-email']['requestBody']['content']['application/json']; export type AdminAccountsFindByEmailResponse = operations['admin___accounts___find-by-email']['responses']['200']['content']['application/json']; +export type AdminAccountsFindByEmailErrors = _Operations_EndpointsErrors['admin___accounts___find-by-email'][keyof _Operations_EndpointsErrors['admin___accounts___find-by-email']]; export type AdminAdCreateRequest = operations['admin___ad___create']['requestBody']['content']['application/json']; export type AdminAdCreateResponse = operations['admin___ad___create']['responses']['200']['content']['application/json']; +export type AdminAdCreateErrors = _Operations_EndpointsErrors['admin___ad___create'][keyof _Operations_EndpointsErrors['admin___ad___create']]; export type AdminAdDeleteRequest = operations['admin___ad___delete']['requestBody']['content']['application/json']; +export type AdminAdDeleteErrors = _Operations_EndpointsErrors['admin___ad___delete'][keyof _Operations_EndpointsErrors['admin___ad___delete']]; export type AdminAdListRequest = operations['admin___ad___list']['requestBody']['content']['application/json']; export type AdminAdListResponse = operations['admin___ad___list']['responses']['200']['content']['application/json']; +export type AdminAdListErrors = _Operations_EndpointsErrors['admin___ad___list'][keyof _Operations_EndpointsErrors['admin___ad___list']]; export type AdminAdUpdateRequest = operations['admin___ad___update']['requestBody']['content']['application/json']; +export type AdminAdUpdateErrors = _Operations_EndpointsErrors['admin___ad___update'][keyof _Operations_EndpointsErrors['admin___ad___update']]; export type AdminAnnouncementsCreateRequest = operations['admin___announcements___create']['requestBody']['content']['application/json']; export type AdminAnnouncementsCreateResponse = operations['admin___announcements___create']['responses']['200']['content']['application/json']; +export type AdminAnnouncementsCreateErrors = _Operations_EndpointsErrors['admin___announcements___create'][keyof _Operations_EndpointsErrors['admin___announcements___create']]; export type AdminAnnouncementsDeleteRequest = operations['admin___announcements___delete']['requestBody']['content']['application/json']; +export type AdminAnnouncementsDeleteErrors = _Operations_EndpointsErrors['admin___announcements___delete'][keyof _Operations_EndpointsErrors['admin___announcements___delete']]; export type AdminAnnouncementsListRequest = operations['admin___announcements___list']['requestBody']['content']['application/json']; export type AdminAnnouncementsListResponse = operations['admin___announcements___list']['responses']['200']['content']['application/json']; +export type AdminAnnouncementsListErrors = _Operations_EndpointsErrors['admin___announcements___list'][keyof _Operations_EndpointsErrors['admin___announcements___list']]; export type AdminAnnouncementsUpdateRequest = operations['admin___announcements___update']['requestBody']['content']['application/json']; +export type AdminAnnouncementsUpdateErrors = _Operations_EndpointsErrors['admin___announcements___update'][keyof _Operations_EndpointsErrors['admin___announcements___update']]; export type AdminAvatarDecorationsCreateRequest = operations['admin___avatar-decorations___create']['requestBody']['content']['application/json']; +export type AdminAvatarDecorationsCreateErrors = _Operations_EndpointsErrors['admin___avatar-decorations___create'][keyof _Operations_EndpointsErrors['admin___avatar-decorations___create']]; export type AdminAvatarDecorationsDeleteRequest = operations['admin___avatar-decorations___delete']['requestBody']['content']['application/json']; +export type AdminAvatarDecorationsDeleteErrors = _Operations_EndpointsErrors['admin___avatar-decorations___delete'][keyof _Operations_EndpointsErrors['admin___avatar-decorations___delete']]; export type AdminAvatarDecorationsListRequest = operations['admin___avatar-decorations___list']['requestBody']['content']['application/json']; export type AdminAvatarDecorationsListResponse = operations['admin___avatar-decorations___list']['responses']['200']['content']['application/json']; +export type AdminAvatarDecorationsListErrors = _Operations_EndpointsErrors['admin___avatar-decorations___list'][keyof _Operations_EndpointsErrors['admin___avatar-decorations___list']]; export type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json']; +export type AdminAvatarDecorationsUpdateErrors = _Operations_EndpointsErrors['admin___avatar-decorations___update'][keyof _Operations_EndpointsErrors['admin___avatar-decorations___update']]; export type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json']; +export type AdminDeleteAllFilesOfAUserErrors = _Operations_EndpointsErrors['admin___delete-all-files-of-a-user'][keyof _Operations_EndpointsErrors['admin___delete-all-files-of-a-user']]; export type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json']; +export type AdminUnsetUserAvatarErrors = _Operations_EndpointsErrors['admin___unset-user-avatar'][keyof _Operations_EndpointsErrors['admin___unset-user-avatar']]; export type AdminUnsetUserBannerRequest = operations['admin___unset-user-banner']['requestBody']['content']['application/json']; +export type AdminUnsetUserBannerErrors = _Operations_EndpointsErrors['admin___unset-user-banner'][keyof _Operations_EndpointsErrors['admin___unset-user-banner']]; +export type AdminDriveCleanRemoteFilesErrors = _Operations_EndpointsErrors['admin___drive___clean-remote-files'][keyof _Operations_EndpointsErrors['admin___drive___clean-remote-files']]; +export type AdminDriveCleanupErrors = _Operations_EndpointsErrors['admin___drive___cleanup'][keyof _Operations_EndpointsErrors['admin___drive___cleanup']]; export type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json']; export type AdminDriveFilesResponse = operations['admin___drive___files']['responses']['200']['content']['application/json']; +export type AdminDriveFilesErrors = _Operations_EndpointsErrors['admin___drive___files'][keyof _Operations_EndpointsErrors['admin___drive___files']]; export type AdminDriveShowFileRequest = operations['admin___drive___show-file']['requestBody']['content']['application/json']; export type AdminDriveShowFileResponse = operations['admin___drive___show-file']['responses']['200']['content']['application/json']; +export type AdminDriveShowFileErrors = _Operations_EndpointsErrors['admin___drive___show-file'][keyof _Operations_EndpointsErrors['admin___drive___show-file']]; export type AdminEmojiAddAliasesBulkRequest = operations['admin___emoji___add-aliases-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiAddAliasesBulkErrors = _Operations_EndpointsErrors['admin___emoji___add-aliases-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___add-aliases-bulk']]; export type AdminEmojiAddRequest = operations['admin___emoji___add']['requestBody']['content']['application/json']; export type AdminEmojiAddResponse = operations['admin___emoji___add']['responses']['200']['content']['application/json']; +export type AdminEmojiAddErrors = _Operations_EndpointsErrors['admin___emoji___add'][keyof _Operations_EndpointsErrors['admin___emoji___add']]; export type AdminEmojiCopyRequest = operations['admin___emoji___copy']['requestBody']['content']['application/json']; export type AdminEmojiCopyResponse = operations['admin___emoji___copy']['responses']['200']['content']['application/json']; +export type AdminEmojiCopyErrors = _Operations_EndpointsErrors['admin___emoji___copy'][keyof _Operations_EndpointsErrors['admin___emoji___copy']]; export type AdminEmojiDeleteBulkRequest = operations['admin___emoji___delete-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiDeleteBulkErrors = _Operations_EndpointsErrors['admin___emoji___delete-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___delete-bulk']]; export type AdminEmojiDeleteRequest = operations['admin___emoji___delete']['requestBody']['content']['application/json']; +export type AdminEmojiDeleteErrors = _Operations_EndpointsErrors['admin___emoji___delete'][keyof _Operations_EndpointsErrors['admin___emoji___delete']]; export type AdminEmojiImportZipRequest = operations['admin___emoji___import-zip']['requestBody']['content']['application/json']; +export type AdminEmojiImportZipErrors = _Operations_EndpointsErrors['admin___emoji___import-zip'][keyof _Operations_EndpointsErrors['admin___emoji___import-zip']]; export type AdminEmojiListRemoteRequest = operations['admin___emoji___list-remote']['requestBody']['content']['application/json']; export type AdminEmojiListRemoteResponse = operations['admin___emoji___list-remote']['responses']['200']['content']['application/json']; +export type AdminEmojiListRemoteErrors = _Operations_EndpointsErrors['admin___emoji___list-remote'][keyof _Operations_EndpointsErrors['admin___emoji___list-remote']]; export type AdminEmojiListRequest = operations['admin___emoji___list']['requestBody']['content']['application/json']; export type AdminEmojiListResponse = operations['admin___emoji___list']['responses']['200']['content']['application/json']; +export type AdminEmojiListErrors = _Operations_EndpointsErrors['admin___emoji___list'][keyof _Operations_EndpointsErrors['admin___emoji___list']]; export type AdminEmojiRemoveAliasesBulkRequest = operations['admin___emoji___remove-aliases-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiRemoveAliasesBulkErrors = _Operations_EndpointsErrors['admin___emoji___remove-aliases-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___remove-aliases-bulk']]; export type AdminEmojiSetAliasesBulkRequest = operations['admin___emoji___set-aliases-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiSetAliasesBulkErrors = _Operations_EndpointsErrors['admin___emoji___set-aliases-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___set-aliases-bulk']]; export type AdminEmojiSetCategoryBulkRequest = operations['admin___emoji___set-category-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiSetCategoryBulkErrors = _Operations_EndpointsErrors['admin___emoji___set-category-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___set-category-bulk']]; export type AdminEmojiSetLicenseBulkRequest = operations['admin___emoji___set-license-bulk']['requestBody']['content']['application/json']; +export type AdminEmojiSetLicenseBulkErrors = _Operations_EndpointsErrors['admin___emoji___set-license-bulk'][keyof _Operations_EndpointsErrors['admin___emoji___set-license-bulk']]; export type AdminEmojiUpdateRequest = operations['admin___emoji___update']['requestBody']['content']['application/json']; +export type AdminEmojiUpdateErrors = _Operations_EndpointsErrors['admin___emoji___update'][keyof _Operations_EndpointsErrors['admin___emoji___update']]; export type AdminFederationDeleteAllFilesRequest = operations['admin___federation___delete-all-files']['requestBody']['content']['application/json']; +export type AdminFederationDeleteAllFilesErrors = _Operations_EndpointsErrors['admin___federation___delete-all-files'][keyof _Operations_EndpointsErrors['admin___federation___delete-all-files']]; export type AdminFederationRefreshRemoteInstanceMetadataRequest = operations['admin___federation___refresh-remote-instance-metadata']['requestBody']['content']['application/json']; +export type AdminFederationRefreshRemoteInstanceMetadataErrors = _Operations_EndpointsErrors['admin___federation___refresh-remote-instance-metadata'][keyof _Operations_EndpointsErrors['admin___federation___refresh-remote-instance-metadata']]; export type AdminFederationRemoveAllFollowingRequest = operations['admin___federation___remove-all-following']['requestBody']['content']['application/json']; +export type AdminFederationRemoveAllFollowingErrors = _Operations_EndpointsErrors['admin___federation___remove-all-following'][keyof _Operations_EndpointsErrors['admin___federation___remove-all-following']]; export type AdminFederationUpdateInstanceRequest = operations['admin___federation___update-instance']['requestBody']['content']['application/json']; +export type AdminFederationUpdateInstanceErrors = _Operations_EndpointsErrors['admin___federation___update-instance'][keyof _Operations_EndpointsErrors['admin___federation___update-instance']]; export type AdminGetIndexStatsResponse = operations['admin___get-index-stats']['responses']['200']['content']['application/json']; +export type AdminGetIndexStatsErrors = _Operations_EndpointsErrors['admin___get-index-stats'][keyof _Operations_EndpointsErrors['admin___get-index-stats']]; export type AdminGetTableStatsResponse = operations['admin___get-table-stats']['responses']['200']['content']['application/json']; +export type AdminGetTableStatsErrors = _Operations_EndpointsErrors['admin___get-table-stats'][keyof _Operations_EndpointsErrors['admin___get-table-stats']]; export type AdminGetUserIpsRequest = operations['admin___get-user-ips']['requestBody']['content']['application/json']; export type AdminGetUserIpsResponse = operations['admin___get-user-ips']['responses']['200']['content']['application/json']; +export type AdminGetUserIpsErrors = _Operations_EndpointsErrors['admin___get-user-ips'][keyof _Operations_EndpointsErrors['admin___get-user-ips']]; export type AdminInviteCreateRequest = operations['admin___invite___create']['requestBody']['content']['application/json']; export type AdminInviteCreateResponse = operations['admin___invite___create']['responses']['200']['content']['application/json']; +export type AdminInviteCreateErrors = _Operations_EndpointsErrors['admin___invite___create'][keyof _Operations_EndpointsErrors['admin___invite___create']]; export type AdminInviteListRequest = operations['admin___invite___list']['requestBody']['content']['application/json']; export type AdminInviteListResponse = operations['admin___invite___list']['responses']['200']['content']['application/json']; +export type AdminInviteListErrors = _Operations_EndpointsErrors['admin___invite___list'][keyof _Operations_EndpointsErrors['admin___invite___list']]; export type AdminPromoCreateRequest = operations['admin___promo___create']['requestBody']['content']['application/json']; +export type AdminPromoCreateErrors = _Operations_EndpointsErrors['admin___promo___create'][keyof _Operations_EndpointsErrors['admin___promo___create']]; +export type AdminQueueClearErrors = _Operations_EndpointsErrors['admin___queue___clear'][keyof _Operations_EndpointsErrors['admin___queue___clear']]; export type AdminQueueDeliverDelayedResponse = operations['admin___queue___deliver-delayed']['responses']['200']['content']['application/json']; +export type AdminQueueDeliverDelayedErrors = _Operations_EndpointsErrors['admin___queue___deliver-delayed'][keyof _Operations_EndpointsErrors['admin___queue___deliver-delayed']]; export type AdminQueueInboxDelayedResponse = operations['admin___queue___inbox-delayed']['responses']['200']['content']['application/json']; +export type AdminQueueInboxDelayedErrors = _Operations_EndpointsErrors['admin___queue___inbox-delayed'][keyof _Operations_EndpointsErrors['admin___queue___inbox-delayed']]; export type AdminQueuePromoteRequest = operations['admin___queue___promote']['requestBody']['content']['application/json']; +export type AdminQueuePromoteErrors = _Operations_EndpointsErrors['admin___queue___promote'][keyof _Operations_EndpointsErrors['admin___queue___promote']]; export type AdminQueueStatsResponse = operations['admin___queue___stats']['responses']['200']['content']['application/json']; +export type AdminQueueStatsErrors = _Operations_EndpointsErrors['admin___queue___stats'][keyof _Operations_EndpointsErrors['admin___queue___stats']]; export type AdminRelaysAddRequest = operations['admin___relays___add']['requestBody']['content']['application/json']; export type AdminRelaysAddResponse = operations['admin___relays___add']['responses']['200']['content']['application/json']; +export type AdminRelaysAddErrors = _Operations_EndpointsErrors['admin___relays___add'][keyof _Operations_EndpointsErrors['admin___relays___add']]; export type AdminRelaysListResponse = operations['admin___relays___list']['responses']['200']['content']['application/json']; +export type AdminRelaysListErrors = _Operations_EndpointsErrors['admin___relays___list'][keyof _Operations_EndpointsErrors['admin___relays___list']]; export type AdminRelaysRemoveRequest = operations['admin___relays___remove']['requestBody']['content']['application/json']; +export type AdminRelaysRemoveErrors = _Operations_EndpointsErrors['admin___relays___remove'][keyof _Operations_EndpointsErrors['admin___relays___remove']]; export type AdminResetPasswordRequest = operations['admin___reset-password']['requestBody']['content']['application/json']; export type AdminResetPasswordResponse = operations['admin___reset-password']['responses']['200']['content']['application/json']; +export type AdminResetPasswordErrors = _Operations_EndpointsErrors['admin___reset-password'][keyof _Operations_EndpointsErrors['admin___reset-password']]; export type AdminResolveAbuseUserReportRequest = operations['admin___resolve-abuse-user-report']['requestBody']['content']['application/json']; +export type AdminResolveAbuseUserReportErrors = _Operations_EndpointsErrors['admin___resolve-abuse-user-report'][keyof _Operations_EndpointsErrors['admin___resolve-abuse-user-report']]; export type AdminSendEmailRequest = operations['admin___send-email']['requestBody']['content']['application/json']; +export type AdminSendEmailErrors = _Operations_EndpointsErrors['admin___send-email'][keyof _Operations_EndpointsErrors['admin___send-email']]; export type AdminServerInfoResponse = operations['admin___server-info']['responses']['200']['content']['application/json']; +export type AdminServerInfoErrors = _Operations_EndpointsErrors['admin___server-info'][keyof _Operations_EndpointsErrors['admin___server-info']]; export type AdminShowModerationLogsRequest = operations['admin___show-moderation-logs']['requestBody']['content']['application/json']; export type AdminShowModerationLogsResponse = operations['admin___show-moderation-logs']['responses']['200']['content']['application/json']; +export type AdminShowModerationLogsErrors = _Operations_EndpointsErrors['admin___show-moderation-logs'][keyof _Operations_EndpointsErrors['admin___show-moderation-logs']]; export type AdminShowUserRequest = operations['admin___show-user']['requestBody']['content']['application/json']; export type AdminShowUserResponse = operations['admin___show-user']['responses']['200']['content']['application/json']; +export type AdminShowUserErrors = _Operations_EndpointsErrors['admin___show-user'][keyof _Operations_EndpointsErrors['admin___show-user']]; export type AdminShowUsersRequest = operations['admin___show-users']['requestBody']['content']['application/json']; export type AdminShowUsersResponse = operations['admin___show-users']['responses']['200']['content']['application/json']; +export type AdminShowUsersErrors = _Operations_EndpointsErrors['admin___show-users'][keyof _Operations_EndpointsErrors['admin___show-users']]; export type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; +export type AdminSuspendUserErrors = _Operations_EndpointsErrors['admin___suspend-user'][keyof _Operations_EndpointsErrors['admin___suspend-user']]; export type AdminUnsuspendUserRequest = operations['admin___unsuspend-user']['requestBody']['content']['application/json']; +export type AdminUnsuspendUserErrors = _Operations_EndpointsErrors['admin___unsuspend-user'][keyof _Operations_EndpointsErrors['admin___unsuspend-user']]; export type AdminUpdateMetaRequest = operations['admin___update-meta']['requestBody']['content']['application/json']; +export type AdminUpdateMetaErrors = _Operations_EndpointsErrors['admin___update-meta'][keyof _Operations_EndpointsErrors['admin___update-meta']]; export type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json']; +export type AdminDeleteAccountErrors = _Operations_EndpointsErrors['admin___delete-account'][keyof _Operations_EndpointsErrors['admin___delete-account']]; export type AdminUpdateUserNoteRequest = operations['admin___update-user-note']['requestBody']['content']['application/json']; +export type AdminUpdateUserNoteErrors = _Operations_EndpointsErrors['admin___update-user-note'][keyof _Operations_EndpointsErrors['admin___update-user-note']]; export type AdminRolesCreateRequest = operations['admin___roles___create']['requestBody']['content']['application/json']; export type AdminRolesCreateResponse = operations['admin___roles___create']['responses']['200']['content']['application/json']; +export type AdminRolesCreateErrors = _Operations_EndpointsErrors['admin___roles___create'][keyof _Operations_EndpointsErrors['admin___roles___create']]; export type AdminRolesDeleteRequest = operations['admin___roles___delete']['requestBody']['content']['application/json']; +export type AdminRolesDeleteErrors = _Operations_EndpointsErrors['admin___roles___delete'][keyof _Operations_EndpointsErrors['admin___roles___delete']]; export type AdminRolesListResponse = operations['admin___roles___list']['responses']['200']['content']['application/json']; +export type AdminRolesListErrors = _Operations_EndpointsErrors['admin___roles___list'][keyof _Operations_EndpointsErrors['admin___roles___list']]; export type AdminRolesShowRequest = operations['admin___roles___show']['requestBody']['content']['application/json']; export type AdminRolesShowResponse = operations['admin___roles___show']['responses']['200']['content']['application/json']; +export type AdminRolesShowErrors = _Operations_EndpointsErrors['admin___roles___show'][keyof _Operations_EndpointsErrors['admin___roles___show']]; export type AdminRolesUpdateRequest = operations['admin___roles___update']['requestBody']['content']['application/json']; +export type AdminRolesUpdateErrors = _Operations_EndpointsErrors['admin___roles___update'][keyof _Operations_EndpointsErrors['admin___roles___update']]; export type AdminRolesAssignRequest = operations['admin___roles___assign']['requestBody']['content']['application/json']; +export type AdminRolesAssignErrors = _Operations_EndpointsErrors['admin___roles___assign'][keyof _Operations_EndpointsErrors['admin___roles___assign']]; export type AdminRolesUnassignRequest = operations['admin___roles___unassign']['requestBody']['content']['application/json']; +export type AdminRolesUnassignErrors = _Operations_EndpointsErrors['admin___roles___unassign'][keyof _Operations_EndpointsErrors['admin___roles___unassign']]; export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json']; +export type AdminRolesUpdateDefaultPoliciesErrors = _Operations_EndpointsErrors['admin___roles___update-default-policies'][keyof _Operations_EndpointsErrors['admin___roles___update-default-policies']]; export type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json']; export type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json']; +export type AdminRolesUsersErrors = _Operations_EndpointsErrors['admin___roles___users'][keyof _Operations_EndpointsErrors['admin___roles___users']]; export type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; export type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookCreateErrors = _Operations_EndpointsErrors['admin___system-webhook___create'][keyof _Operations_EndpointsErrors['admin___system-webhook___create']]; export type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; +export type AdminSystemWebhookDeleteErrors = _Operations_EndpointsErrors['admin___system-webhook___delete'][keyof _Operations_EndpointsErrors['admin___system-webhook___delete']]; export type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; export type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookListErrors = _Operations_EndpointsErrors['admin___system-webhook___list'][keyof _Operations_EndpointsErrors['admin___system-webhook___list']]; export type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; export type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookShowErrors = _Operations_EndpointsErrors['admin___system-webhook___show'][keyof _Operations_EndpointsErrors['admin___system-webhook___show']]; export type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; export type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookUpdateErrors = _Operations_EndpointsErrors['admin___system-webhook___update'][keyof _Operations_EndpointsErrors['admin___system-webhook___update']]; export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json']; export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json']; +export type AnnouncementsErrors = _Operations_EndpointsErrors['announcements'][keyof _Operations_EndpointsErrors['announcements']]; export type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json']; export type AnnouncementsShowResponse = operations['announcements___show']['responses']['200']['content']['application/json']; +export type AnnouncementsShowErrors = _Operations_EndpointsErrors['announcements___show'][keyof _Operations_EndpointsErrors['announcements___show']]; export type AntennasCreateRequest = operations['antennas___create']['requestBody']['content']['application/json']; export type AntennasCreateResponse = operations['antennas___create']['responses']['200']['content']['application/json']; +export type AntennasCreateErrors = _Operations_EndpointsErrors['antennas___create'][keyof _Operations_EndpointsErrors['antennas___create']]; export type AntennasDeleteRequest = operations['antennas___delete']['requestBody']['content']['application/json']; +export type AntennasDeleteErrors = _Operations_EndpointsErrors['antennas___delete'][keyof _Operations_EndpointsErrors['antennas___delete']]; export type AntennasListResponse = operations['antennas___list']['responses']['200']['content']['application/json']; +export type AntennasListErrors = _Operations_EndpointsErrors['antennas___list'][keyof _Operations_EndpointsErrors['antennas___list']]; export type AntennasNotesRequest = operations['antennas___notes']['requestBody']['content']['application/json']; export type AntennasNotesResponse = operations['antennas___notes']['responses']['200']['content']['application/json']; +export type AntennasNotesErrors = _Operations_EndpointsErrors['antennas___notes'][keyof _Operations_EndpointsErrors['antennas___notes']]; export type AntennasShowRequest = operations['antennas___show']['requestBody']['content']['application/json']; export type AntennasShowResponse = operations['antennas___show']['responses']['200']['content']['application/json']; +export type AntennasShowErrors = _Operations_EndpointsErrors['antennas___show'][keyof _Operations_EndpointsErrors['antennas___show']]; export type AntennasUpdateRequest = operations['antennas___update']['requestBody']['content']['application/json']; export type AntennasUpdateResponse = operations['antennas___update']['responses']['200']['content']['application/json']; +export type AntennasUpdateErrors = _Operations_EndpointsErrors['antennas___update'][keyof _Operations_EndpointsErrors['antennas___update']]; export type ApGetRequest = operations['ap___get']['requestBody']['content']['application/json']; export type ApGetResponse = operations['ap___get']['responses']['200']['content']['application/json']; +export type ApGetErrors = _Operations_EndpointsErrors['ap___get'][keyof _Operations_EndpointsErrors['ap___get']]; export type ApShowRequest = operations['ap___show']['requestBody']['content']['application/json']; export type ApShowResponse = operations['ap___show']['responses']['200']['content']['application/json']; +export type ApShowErrors = _Operations_EndpointsErrors['ap___show'][keyof _Operations_EndpointsErrors['ap___show']]; export type AppCreateRequest = operations['app___create']['requestBody']['content']['application/json']; export type AppCreateResponse = operations['app___create']['responses']['200']['content']['application/json']; +export type AppCreateErrors = _Operations_EndpointsErrors['app___create'][keyof _Operations_EndpointsErrors['app___create']]; export type AppShowRequest = operations['app___show']['requestBody']['content']['application/json']; export type AppShowResponse = operations['app___show']['responses']['200']['content']['application/json']; +export type AppShowErrors = _Operations_EndpointsErrors['app___show'][keyof _Operations_EndpointsErrors['app___show']]; export type AuthAcceptRequest = operations['auth___accept']['requestBody']['content']['application/json']; +export type AuthAcceptErrors = _Operations_EndpointsErrors['auth___accept'][keyof _Operations_EndpointsErrors['auth___accept']]; export type AuthSessionGenerateRequest = operations['auth___session___generate']['requestBody']['content']['application/json']; export type AuthSessionGenerateResponse = operations['auth___session___generate']['responses']['200']['content']['application/json']; +export type AuthSessionGenerateErrors = _Operations_EndpointsErrors['auth___session___generate'][keyof _Operations_EndpointsErrors['auth___session___generate']]; export type AuthSessionShowRequest = operations['auth___session___show']['requestBody']['content']['application/json']; export type AuthSessionShowResponse = operations['auth___session___show']['responses']['200']['content']['application/json']; +export type AuthSessionShowErrors = _Operations_EndpointsErrors['auth___session___show'][keyof _Operations_EndpointsErrors['auth___session___show']]; export type AuthSessionUserkeyRequest = operations['auth___session___userkey']['requestBody']['content']['application/json']; export type AuthSessionUserkeyResponse = operations['auth___session___userkey']['responses']['200']['content']['application/json']; +export type AuthSessionUserkeyErrors = _Operations_EndpointsErrors['auth___session___userkey'][keyof _Operations_EndpointsErrors['auth___session___userkey']]; export type BlockingCreateRequest = operations['blocking___create']['requestBody']['content']['application/json']; export type BlockingCreateResponse = operations['blocking___create']['responses']['200']['content']['application/json']; +export type BlockingCreateErrors = _Operations_EndpointsErrors['blocking___create'][keyof _Operations_EndpointsErrors['blocking___create']]; export type BlockingDeleteRequest = operations['blocking___delete']['requestBody']['content']['application/json']; export type BlockingDeleteResponse = operations['blocking___delete']['responses']['200']['content']['application/json']; +export type BlockingDeleteErrors = _Operations_EndpointsErrors['blocking___delete'][keyof _Operations_EndpointsErrors['blocking___delete']]; export type BlockingListRequest = operations['blocking___list']['requestBody']['content']['application/json']; export type BlockingListResponse = operations['blocking___list']['responses']['200']['content']['application/json']; +export type BlockingListErrors = _Operations_EndpointsErrors['blocking___list'][keyof _Operations_EndpointsErrors['blocking___list']]; export type ChannelsCreateRequest = operations['channels___create']['requestBody']['content']['application/json']; export type ChannelsCreateResponse = operations['channels___create']['responses']['200']['content']['application/json']; +export type ChannelsCreateErrors = _Operations_EndpointsErrors['channels___create'][keyof _Operations_EndpointsErrors['channels___create']]; export type ChannelsFeaturedResponse = operations['channels___featured']['responses']['200']['content']['application/json']; +export type ChannelsFeaturedErrors = _Operations_EndpointsErrors['channels___featured'][keyof _Operations_EndpointsErrors['channels___featured']]; export type ChannelsFollowRequest = operations['channels___follow']['requestBody']['content']['application/json']; +export type ChannelsFollowErrors = _Operations_EndpointsErrors['channels___follow'][keyof _Operations_EndpointsErrors['channels___follow']]; export type ChannelsFollowedRequest = operations['channels___followed']['requestBody']['content']['application/json']; export type ChannelsFollowedResponse = operations['channels___followed']['responses']['200']['content']['application/json']; +export type ChannelsFollowedErrors = _Operations_EndpointsErrors['channels___followed'][keyof _Operations_EndpointsErrors['channels___followed']]; export type ChannelsOwnedRequest = operations['channels___owned']['requestBody']['content']['application/json']; export type ChannelsOwnedResponse = operations['channels___owned']['responses']['200']['content']['application/json']; +export type ChannelsOwnedErrors = _Operations_EndpointsErrors['channels___owned'][keyof _Operations_EndpointsErrors['channels___owned']]; export type ChannelsShowRequest = operations['channels___show']['requestBody']['content']['application/json']; export type ChannelsShowResponse = operations['channels___show']['responses']['200']['content']['application/json']; +export type ChannelsShowErrors = _Operations_EndpointsErrors['channels___show'][keyof _Operations_EndpointsErrors['channels___show']]; export type ChannelsTimelineRequest = operations['channels___timeline']['requestBody']['content']['application/json']; export type ChannelsTimelineResponse = operations['channels___timeline']['responses']['200']['content']['application/json']; +export type ChannelsTimelineErrors = _Operations_EndpointsErrors['channels___timeline'][keyof _Operations_EndpointsErrors['channels___timeline']]; export type ChannelsUnfollowRequest = operations['channels___unfollow']['requestBody']['content']['application/json']; +export type ChannelsUnfollowErrors = _Operations_EndpointsErrors['channels___unfollow'][keyof _Operations_EndpointsErrors['channels___unfollow']]; export type ChannelsUpdateRequest = operations['channels___update']['requestBody']['content']['application/json']; export type ChannelsUpdateResponse = operations['channels___update']['responses']['200']['content']['application/json']; +export type ChannelsUpdateErrors = _Operations_EndpointsErrors['channels___update'][keyof _Operations_EndpointsErrors['channels___update']]; export type ChannelsFavoriteRequest = operations['channels___favorite']['requestBody']['content']['application/json']; +export type ChannelsFavoriteErrors = _Operations_EndpointsErrors['channels___favorite'][keyof _Operations_EndpointsErrors['channels___favorite']]; export type ChannelsUnfavoriteRequest = operations['channels___unfavorite']['requestBody']['content']['application/json']; +export type ChannelsUnfavoriteErrors = _Operations_EndpointsErrors['channels___unfavorite'][keyof _Operations_EndpointsErrors['channels___unfavorite']]; export type ChannelsMyFavoritesResponse = operations['channels___my-favorites']['responses']['200']['content']['application/json']; +export type ChannelsMyFavoritesErrors = _Operations_EndpointsErrors['channels___my-favorites'][keyof _Operations_EndpointsErrors['channels___my-favorites']]; export type ChannelsSearchRequest = operations['channels___search']['requestBody']['content']['application/json']; export type ChannelsSearchResponse = operations['channels___search']['responses']['200']['content']['application/json']; +export type ChannelsSearchErrors = _Operations_EndpointsErrors['channels___search'][keyof _Operations_EndpointsErrors['channels___search']]; export type ChartsActiveUsersRequest = operations['charts___active-users']['requestBody']['content']['application/json']; export type ChartsActiveUsersResponse = operations['charts___active-users']['responses']['200']['content']['application/json']; +export type ChartsActiveUsersErrors = _Operations_EndpointsErrors['charts___active-users'][keyof _Operations_EndpointsErrors['charts___active-users']]; export type ChartsApRequestRequest = operations['charts___ap-request']['requestBody']['content']['application/json']; export type ChartsApRequestResponse = operations['charts___ap-request']['responses']['200']['content']['application/json']; +export type ChartsApRequestErrors = _Operations_EndpointsErrors['charts___ap-request'][keyof _Operations_EndpointsErrors['charts___ap-request']]; export type ChartsDriveRequest = operations['charts___drive']['requestBody']['content']['application/json']; export type ChartsDriveResponse = operations['charts___drive']['responses']['200']['content']['application/json']; +export type ChartsDriveErrors = _Operations_EndpointsErrors['charts___drive'][keyof _Operations_EndpointsErrors['charts___drive']]; export type ChartsFederationRequest = operations['charts___federation']['requestBody']['content']['application/json']; export type ChartsFederationResponse = operations['charts___federation']['responses']['200']['content']['application/json']; +export type ChartsFederationErrors = _Operations_EndpointsErrors['charts___federation'][keyof _Operations_EndpointsErrors['charts___federation']]; export type ChartsInstanceRequest = operations['charts___instance']['requestBody']['content']['application/json']; export type ChartsInstanceResponse = operations['charts___instance']['responses']['200']['content']['application/json']; +export type ChartsInstanceErrors = _Operations_EndpointsErrors['charts___instance'][keyof _Operations_EndpointsErrors['charts___instance']]; export type ChartsNotesRequest = operations['charts___notes']['requestBody']['content']['application/json']; export type ChartsNotesResponse = operations['charts___notes']['responses']['200']['content']['application/json']; +export type ChartsNotesErrors = _Operations_EndpointsErrors['charts___notes'][keyof _Operations_EndpointsErrors['charts___notes']]; export type ChartsUserDriveRequest = operations['charts___user___drive']['requestBody']['content']['application/json']; export type ChartsUserDriveResponse = operations['charts___user___drive']['responses']['200']['content']['application/json']; +export type ChartsUserDriveErrors = _Operations_EndpointsErrors['charts___user___drive'][keyof _Operations_EndpointsErrors['charts___user___drive']]; export type ChartsUserFollowingRequest = operations['charts___user___following']['requestBody']['content']['application/json']; export type ChartsUserFollowingResponse = operations['charts___user___following']['responses']['200']['content']['application/json']; +export type ChartsUserFollowingErrors = _Operations_EndpointsErrors['charts___user___following'][keyof _Operations_EndpointsErrors['charts___user___following']]; export type ChartsUserNotesRequest = operations['charts___user___notes']['requestBody']['content']['application/json']; export type ChartsUserNotesResponse = operations['charts___user___notes']['responses']['200']['content']['application/json']; +export type ChartsUserNotesErrors = _Operations_EndpointsErrors['charts___user___notes'][keyof _Operations_EndpointsErrors['charts___user___notes']]; export type ChartsUserPvRequest = operations['charts___user___pv']['requestBody']['content']['application/json']; export type ChartsUserPvResponse = operations['charts___user___pv']['responses']['200']['content']['application/json']; +export type ChartsUserPvErrors = _Operations_EndpointsErrors['charts___user___pv'][keyof _Operations_EndpointsErrors['charts___user___pv']]; export type ChartsUserReactionsRequest = operations['charts___user___reactions']['requestBody']['content']['application/json']; export type ChartsUserReactionsResponse = operations['charts___user___reactions']['responses']['200']['content']['application/json']; +export type ChartsUserReactionsErrors = _Operations_EndpointsErrors['charts___user___reactions'][keyof _Operations_EndpointsErrors['charts___user___reactions']]; export type ChartsUsersRequest = operations['charts___users']['requestBody']['content']['application/json']; export type ChartsUsersResponse = operations['charts___users']['responses']['200']['content']['application/json']; +export type ChartsUsersErrors = _Operations_EndpointsErrors['charts___users'][keyof _Operations_EndpointsErrors['charts___users']]; export type ClipsAddNoteRequest = operations['clips___add-note']['requestBody']['content']['application/json']; +export type ClipsAddNoteErrors = _Operations_EndpointsErrors['clips___add-note'][keyof _Operations_EndpointsErrors['clips___add-note']]; export type ClipsRemoveNoteRequest = operations['clips___remove-note']['requestBody']['content']['application/json']; +export type ClipsRemoveNoteErrors = _Operations_EndpointsErrors['clips___remove-note'][keyof _Operations_EndpointsErrors['clips___remove-note']]; export type ClipsCreateRequest = operations['clips___create']['requestBody']['content']['application/json']; export type ClipsCreateResponse = operations['clips___create']['responses']['200']['content']['application/json']; +export type ClipsCreateErrors = _Operations_EndpointsErrors['clips___create'][keyof _Operations_EndpointsErrors['clips___create']]; export type ClipsDeleteRequest = operations['clips___delete']['requestBody']['content']['application/json']; +export type ClipsDeleteErrors = _Operations_EndpointsErrors['clips___delete'][keyof _Operations_EndpointsErrors['clips___delete']]; export type ClipsListResponse = operations['clips___list']['responses']['200']['content']['application/json']; +export type ClipsListErrors = _Operations_EndpointsErrors['clips___list'][keyof _Operations_EndpointsErrors['clips___list']]; export type ClipsNotesRequest = operations['clips___notes']['requestBody']['content']['application/json']; export type ClipsNotesResponse = operations['clips___notes']['responses']['200']['content']['application/json']; +export type ClipsNotesErrors = _Operations_EndpointsErrors['clips___notes'][keyof _Operations_EndpointsErrors['clips___notes']]; export type ClipsShowRequest = operations['clips___show']['requestBody']['content']['application/json']; export type ClipsShowResponse = operations['clips___show']['responses']['200']['content']['application/json']; +export type ClipsShowErrors = _Operations_EndpointsErrors['clips___show'][keyof _Operations_EndpointsErrors['clips___show']]; export type ClipsUpdateRequest = operations['clips___update']['requestBody']['content']['application/json']; export type ClipsUpdateResponse = operations['clips___update']['responses']['200']['content']['application/json']; +export type ClipsUpdateErrors = _Operations_EndpointsErrors['clips___update'][keyof _Operations_EndpointsErrors['clips___update']]; export type ClipsFavoriteRequest = operations['clips___favorite']['requestBody']['content']['application/json']; +export type ClipsFavoriteErrors = _Operations_EndpointsErrors['clips___favorite'][keyof _Operations_EndpointsErrors['clips___favorite']]; export type ClipsUnfavoriteRequest = operations['clips___unfavorite']['requestBody']['content']['application/json']; +export type ClipsUnfavoriteErrors = _Operations_EndpointsErrors['clips___unfavorite'][keyof _Operations_EndpointsErrors['clips___unfavorite']]; export type ClipsMyFavoritesResponse = operations['clips___my-favorites']['responses']['200']['content']['application/json']; +export type ClipsMyFavoritesErrors = _Operations_EndpointsErrors['clips___my-favorites'][keyof _Operations_EndpointsErrors['clips___my-favorites']]; export type DriveResponse = operations['drive']['responses']['200']['content']['application/json']; +export type DriveErrors = _Operations_EndpointsErrors['drive'][keyof _Operations_EndpointsErrors['drive']]; export type DriveFilesRequest = operations['drive___files']['requestBody']['content']['application/json']; export type DriveFilesResponse = operations['drive___files']['responses']['200']['content']['application/json']; +export type DriveFilesErrors = _Operations_EndpointsErrors['drive___files'][keyof _Operations_EndpointsErrors['drive___files']]; export type DriveFilesAttachedNotesRequest = operations['drive___files___attached-notes']['requestBody']['content']['application/json']; export type DriveFilesAttachedNotesResponse = operations['drive___files___attached-notes']['responses']['200']['content']['application/json']; +export type DriveFilesAttachedNotesErrors = _Operations_EndpointsErrors['drive___files___attached-notes'][keyof _Operations_EndpointsErrors['drive___files___attached-notes']]; export type DriveFilesCheckExistenceRequest = operations['drive___files___check-existence']['requestBody']['content']['application/json']; export type DriveFilesCheckExistenceResponse = operations['drive___files___check-existence']['responses']['200']['content']['application/json']; +export type DriveFilesCheckExistenceErrors = _Operations_EndpointsErrors['drive___files___check-existence'][keyof _Operations_EndpointsErrors['drive___files___check-existence']]; export type DriveFilesCreateRequest = operations['drive___files___create']['requestBody']['content']['multipart/form-data']; export type DriveFilesCreateResponse = operations['drive___files___create']['responses']['200']['content']['application/json']; +export type DriveFilesCreateErrors = _Operations_EndpointsErrors['drive___files___create'][keyof _Operations_EndpointsErrors['drive___files___create']]; export type DriveFilesDeleteRequest = operations['drive___files___delete']['requestBody']['content']['application/json']; +export type DriveFilesDeleteErrors = _Operations_EndpointsErrors['drive___files___delete'][keyof _Operations_EndpointsErrors['drive___files___delete']]; export type DriveFilesFindByHashRequest = operations['drive___files___find-by-hash']['requestBody']['content']['application/json']; export type DriveFilesFindByHashResponse = operations['drive___files___find-by-hash']['responses']['200']['content']['application/json']; +export type DriveFilesFindByHashErrors = _Operations_EndpointsErrors['drive___files___find-by-hash'][keyof _Operations_EndpointsErrors['drive___files___find-by-hash']]; export type DriveFilesFindRequest = operations['drive___files___find']['requestBody']['content']['application/json']; export type DriveFilesFindResponse = operations['drive___files___find']['responses']['200']['content']['application/json']; +export type DriveFilesFindErrors = _Operations_EndpointsErrors['drive___files___find'][keyof _Operations_EndpointsErrors['drive___files___find']]; export type DriveFilesShowRequest = operations['drive___files___show']['requestBody']['content']['application/json']; export type DriveFilesShowResponse = operations['drive___files___show']['responses']['200']['content']['application/json']; +export type DriveFilesShowErrors = _Operations_EndpointsErrors['drive___files___show'][keyof _Operations_EndpointsErrors['drive___files___show']]; export type DriveFilesUpdateRequest = operations['drive___files___update']['requestBody']['content']['application/json']; export type DriveFilesUpdateResponse = operations['drive___files___update']['responses']['200']['content']['application/json']; +export type DriveFilesUpdateErrors = _Operations_EndpointsErrors['drive___files___update'][keyof _Operations_EndpointsErrors['drive___files___update']]; export type DriveFilesUploadFromUrlRequest = operations['drive___files___upload-from-url']['requestBody']['content']['application/json']; +export type DriveFilesUploadFromUrlErrors = _Operations_EndpointsErrors['drive___files___upload-from-url'][keyof _Operations_EndpointsErrors['drive___files___upload-from-url']]; export type DriveFoldersRequest = operations['drive___folders']['requestBody']['content']['application/json']; export type DriveFoldersResponse = operations['drive___folders']['responses']['200']['content']['application/json']; +export type DriveFoldersErrors = _Operations_EndpointsErrors['drive___folders'][keyof _Operations_EndpointsErrors['drive___folders']]; export type DriveFoldersCreateRequest = operations['drive___folders___create']['requestBody']['content']['application/json']; export type DriveFoldersCreateResponse = operations['drive___folders___create']['responses']['200']['content']['application/json']; +export type DriveFoldersCreateErrors = _Operations_EndpointsErrors['drive___folders___create'][keyof _Operations_EndpointsErrors['drive___folders___create']]; export type DriveFoldersDeleteRequest = operations['drive___folders___delete']['requestBody']['content']['application/json']; +export type DriveFoldersDeleteErrors = _Operations_EndpointsErrors['drive___folders___delete'][keyof _Operations_EndpointsErrors['drive___folders___delete']]; export type DriveFoldersFindRequest = operations['drive___folders___find']['requestBody']['content']['application/json']; export type DriveFoldersFindResponse = operations['drive___folders___find']['responses']['200']['content']['application/json']; +export type DriveFoldersFindErrors = _Operations_EndpointsErrors['drive___folders___find'][keyof _Operations_EndpointsErrors['drive___folders___find']]; export type DriveFoldersShowRequest = operations['drive___folders___show']['requestBody']['content']['application/json']; export type DriveFoldersShowResponse = operations['drive___folders___show']['responses']['200']['content']['application/json']; +export type DriveFoldersShowErrors = _Operations_EndpointsErrors['drive___folders___show'][keyof _Operations_EndpointsErrors['drive___folders___show']]; export type DriveFoldersUpdateRequest = operations['drive___folders___update']['requestBody']['content']['application/json']; export type DriveFoldersUpdateResponse = operations['drive___folders___update']['responses']['200']['content']['application/json']; +export type DriveFoldersUpdateErrors = _Operations_EndpointsErrors['drive___folders___update'][keyof _Operations_EndpointsErrors['drive___folders___update']]; export type DriveStreamRequest = operations['drive___stream']['requestBody']['content']['application/json']; export type DriveStreamResponse = operations['drive___stream']['responses']['200']['content']['application/json']; +export type DriveStreamErrors = _Operations_EndpointsErrors['drive___stream'][keyof _Operations_EndpointsErrors['drive___stream']]; export type EmailAddressAvailableRequest = operations['email-address___available']['requestBody']['content']['application/json']; export type EmailAddressAvailableResponse = operations['email-address___available']['responses']['200']['content']['application/json']; +export type EmailAddressAvailableErrors = _Operations_EndpointsErrors['email-address___available'][keyof _Operations_EndpointsErrors['email-address___available']]; export type EndpointRequest = operations['endpoint']['requestBody']['content']['application/json']; export type EndpointResponse = operations['endpoint']['responses']['200']['content']['application/json']; +export type EndpointErrors = _Operations_EndpointsErrors['endpoint'][keyof _Operations_EndpointsErrors['endpoint']]; export type EndpointsResponse = operations['endpoints']['responses']['200']['content']['application/json']; +export type EndpointsErrors = _Operations_EndpointsErrors['endpoints'][keyof _Operations_EndpointsErrors['endpoints']]; +export type ExportCustomEmojisErrors = _Operations_EndpointsErrors['export-custom-emojis'][keyof _Operations_EndpointsErrors['export-custom-emojis']]; export type FederationFollowersRequest = operations['federation___followers']['requestBody']['content']['application/json']; export type FederationFollowersResponse = operations['federation___followers']['responses']['200']['content']['application/json']; +export type FederationFollowersErrors = _Operations_EndpointsErrors['federation___followers'][keyof _Operations_EndpointsErrors['federation___followers']]; export type FederationFollowingRequest = operations['federation___following']['requestBody']['content']['application/json']; export type FederationFollowingResponse = operations['federation___following']['responses']['200']['content']['application/json']; +export type FederationFollowingErrors = _Operations_EndpointsErrors['federation___following'][keyof _Operations_EndpointsErrors['federation___following']]; export type FederationInstancesRequest = operations['federation___instances']['requestBody']['content']['application/json']; export type FederationInstancesResponse = operations['federation___instances']['responses']['200']['content']['application/json']; +export type FederationInstancesErrors = _Operations_EndpointsErrors['federation___instances'][keyof _Operations_EndpointsErrors['federation___instances']]; export type FederationShowInstanceRequest = operations['federation___show-instance']['requestBody']['content']['application/json']; export type FederationShowInstanceResponse = operations['federation___show-instance']['responses']['200']['content']['application/json']; +export type FederationShowInstanceErrors = _Operations_EndpointsErrors['federation___show-instance'][keyof _Operations_EndpointsErrors['federation___show-instance']]; export type FederationUpdateRemoteUserRequest = operations['federation___update-remote-user']['requestBody']['content']['application/json']; +export type FederationUpdateRemoteUserErrors = _Operations_EndpointsErrors['federation___update-remote-user'][keyof _Operations_EndpointsErrors['federation___update-remote-user']]; export type FederationUsersRequest = operations['federation___users']['requestBody']['content']['application/json']; export type FederationUsersResponse = operations['federation___users']['responses']['200']['content']['application/json']; +export type FederationUsersErrors = _Operations_EndpointsErrors['federation___users'][keyof _Operations_EndpointsErrors['federation___users']]; export type FederationStatsRequest = operations['federation___stats']['requestBody']['content']['application/json']; export type FederationStatsResponse = operations['federation___stats']['responses']['200']['content']['application/json']; +export type FederationStatsErrors = _Operations_EndpointsErrors['federation___stats'][keyof _Operations_EndpointsErrors['federation___stats']]; export type FollowingCreateRequest = operations['following___create']['requestBody']['content']['application/json']; export type FollowingCreateResponse = operations['following___create']['responses']['200']['content']['application/json']; +export type FollowingCreateErrors = _Operations_EndpointsErrors['following___create'][keyof _Operations_EndpointsErrors['following___create']]; export type FollowingDeleteRequest = operations['following___delete']['requestBody']['content']['application/json']; export type FollowingDeleteResponse = operations['following___delete']['responses']['200']['content']['application/json']; +export type FollowingDeleteErrors = _Operations_EndpointsErrors['following___delete'][keyof _Operations_EndpointsErrors['following___delete']]; export type FollowingUpdateRequest = operations['following___update']['requestBody']['content']['application/json']; export type FollowingUpdateResponse = operations['following___update']['responses']['200']['content']['application/json']; +export type FollowingUpdateErrors = _Operations_EndpointsErrors['following___update'][keyof _Operations_EndpointsErrors['following___update']]; export type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json']; +export type FollowingUpdateAllErrors = _Operations_EndpointsErrors['following___update-all'][keyof _Operations_EndpointsErrors['following___update-all']]; export type FollowingInvalidateRequest = operations['following___invalidate']['requestBody']['content']['application/json']; export type FollowingInvalidateResponse = operations['following___invalidate']['responses']['200']['content']['application/json']; +export type FollowingInvalidateErrors = _Operations_EndpointsErrors['following___invalidate'][keyof _Operations_EndpointsErrors['following___invalidate']]; export type FollowingRequestsAcceptRequest = operations['following___requests___accept']['requestBody']['content']['application/json']; +export type FollowingRequestsAcceptErrors = _Operations_EndpointsErrors['following___requests___accept'][keyof _Operations_EndpointsErrors['following___requests___accept']]; export type FollowingRequestsCancelRequest = operations['following___requests___cancel']['requestBody']['content']['application/json']; export type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json']; +export type FollowingRequestsCancelErrors = _Operations_EndpointsErrors['following___requests___cancel'][keyof _Operations_EndpointsErrors['following___requests___cancel']]; export type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json']; export type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json']; +export type FollowingRequestsListErrors = _Operations_EndpointsErrors['following___requests___list'][keyof _Operations_EndpointsErrors['following___requests___list']]; export type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json']; +export type FollowingRequestsRejectErrors = _Operations_EndpointsErrors['following___requests___reject'][keyof _Operations_EndpointsErrors['following___requests___reject']]; export type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json']; export type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json']; +export type GalleryFeaturedErrors = _Operations_EndpointsErrors['gallery___featured'][keyof _Operations_EndpointsErrors['gallery___featured']]; export type GalleryPopularResponse = operations['gallery___popular']['responses']['200']['content']['application/json']; +export type GalleryPopularErrors = _Operations_EndpointsErrors['gallery___popular'][keyof _Operations_EndpointsErrors['gallery___popular']]; export type GalleryPostsRequest = operations['gallery___posts']['requestBody']['content']['application/json']; export type GalleryPostsResponse = operations['gallery___posts']['responses']['200']['content']['application/json']; +export type GalleryPostsErrors = _Operations_EndpointsErrors['gallery___posts'][keyof _Operations_EndpointsErrors['gallery___posts']]; export type GalleryPostsCreateRequest = operations['gallery___posts___create']['requestBody']['content']['application/json']; export type GalleryPostsCreateResponse = operations['gallery___posts___create']['responses']['200']['content']['application/json']; +export type GalleryPostsCreateErrors = _Operations_EndpointsErrors['gallery___posts___create'][keyof _Operations_EndpointsErrors['gallery___posts___create']]; export type GalleryPostsDeleteRequest = operations['gallery___posts___delete']['requestBody']['content']['application/json']; +export type GalleryPostsDeleteErrors = _Operations_EndpointsErrors['gallery___posts___delete'][keyof _Operations_EndpointsErrors['gallery___posts___delete']]; export type GalleryPostsLikeRequest = operations['gallery___posts___like']['requestBody']['content']['application/json']; +export type GalleryPostsLikeErrors = _Operations_EndpointsErrors['gallery___posts___like'][keyof _Operations_EndpointsErrors['gallery___posts___like']]; export type GalleryPostsShowRequest = operations['gallery___posts___show']['requestBody']['content']['application/json']; export type GalleryPostsShowResponse = operations['gallery___posts___show']['responses']['200']['content']['application/json']; +export type GalleryPostsShowErrors = _Operations_EndpointsErrors['gallery___posts___show'][keyof _Operations_EndpointsErrors['gallery___posts___show']]; export type GalleryPostsUnlikeRequest = operations['gallery___posts___unlike']['requestBody']['content']['application/json']; +export type GalleryPostsUnlikeErrors = _Operations_EndpointsErrors['gallery___posts___unlike'][keyof _Operations_EndpointsErrors['gallery___posts___unlike']]; export type GalleryPostsUpdateRequest = operations['gallery___posts___update']['requestBody']['content']['application/json']; export type GalleryPostsUpdateResponse = operations['gallery___posts___update']['responses']['200']['content']['application/json']; +export type GalleryPostsUpdateErrors = _Operations_EndpointsErrors['gallery___posts___update'][keyof _Operations_EndpointsErrors['gallery___posts___update']]; export type GetOnlineUsersCountResponse = operations['get-online-users-count']['responses']['200']['content']['application/json']; +export type GetOnlineUsersCountErrors = _Operations_EndpointsErrors['get-online-users-count'][keyof _Operations_EndpointsErrors['get-online-users-count']]; export type GetAvatarDecorationsResponse = operations['get-avatar-decorations']['responses']['200']['content']['application/json']; +export type GetAvatarDecorationsErrors = _Operations_EndpointsErrors['get-avatar-decorations'][keyof _Operations_EndpointsErrors['get-avatar-decorations']]; export type HashtagsListRequest = operations['hashtags___list']['requestBody']['content']['application/json']; export type HashtagsListResponse = operations['hashtags___list']['responses']['200']['content']['application/json']; +export type HashtagsListErrors = _Operations_EndpointsErrors['hashtags___list'][keyof _Operations_EndpointsErrors['hashtags___list']]; export type HashtagsSearchRequest = operations['hashtags___search']['requestBody']['content']['application/json']; export type HashtagsSearchResponse = operations['hashtags___search']['responses']['200']['content']['application/json']; +export type HashtagsSearchErrors = _Operations_EndpointsErrors['hashtags___search'][keyof _Operations_EndpointsErrors['hashtags___search']]; export type HashtagsShowRequest = operations['hashtags___show']['requestBody']['content']['application/json']; export type HashtagsShowResponse = operations['hashtags___show']['responses']['200']['content']['application/json']; +export type HashtagsShowErrors = _Operations_EndpointsErrors['hashtags___show'][keyof _Operations_EndpointsErrors['hashtags___show']]; export type HashtagsTrendResponse = operations['hashtags___trend']['responses']['200']['content']['application/json']; +export type HashtagsTrendErrors = _Operations_EndpointsErrors['hashtags___trend'][keyof _Operations_EndpointsErrors['hashtags___trend']]; export type HashtagsUsersRequest = operations['hashtags___users']['requestBody']['content']['application/json']; export type HashtagsUsersResponse = operations['hashtags___users']['responses']['200']['content']['application/json']; +export type HashtagsUsersErrors = _Operations_EndpointsErrors['hashtags___users'][keyof _Operations_EndpointsErrors['hashtags___users']]; export type IResponse = operations['i']['responses']['200']['content']['application/json']; +export type IErrors = _Operations_EndpointsErrors['i'][keyof _Operations_EndpointsErrors['i']]; export type I2faDoneRequest = operations['i___2fa___done']['requestBody']['content']['application/json']; export type I2faDoneResponse = operations['i___2fa___done']['responses']['200']['content']['application/json']; +export type I2faDoneErrors = _Operations_EndpointsErrors['i___2fa___done'][keyof _Operations_EndpointsErrors['i___2fa___done']]; export type I2faKeyDoneRequest = operations['i___2fa___key-done']['requestBody']['content']['application/json']; export type I2faKeyDoneResponse = operations['i___2fa___key-done']['responses']['200']['content']['application/json']; +export type I2faKeyDoneErrors = _Operations_EndpointsErrors['i___2fa___key-done'][keyof _Operations_EndpointsErrors['i___2fa___key-done']]; export type I2faPasswordLessRequest = operations['i___2fa___password-less']['requestBody']['content']['application/json']; +export type I2faPasswordLessErrors = _Operations_EndpointsErrors['i___2fa___password-less'][keyof _Operations_EndpointsErrors['i___2fa___password-less']]; export type I2faRegisterKeyRequest = operations['i___2fa___register-key']['requestBody']['content']['application/json']; export type I2faRegisterKeyResponse = operations['i___2fa___register-key']['responses']['200']['content']['application/json']; +export type I2faRegisterKeyErrors = _Operations_EndpointsErrors['i___2fa___register-key'][keyof _Operations_EndpointsErrors['i___2fa___register-key']]; export type I2faRegisterRequest = operations['i___2fa___register']['requestBody']['content']['application/json']; export type I2faRegisterResponse = operations['i___2fa___register']['responses']['200']['content']['application/json']; +export type I2faRegisterErrors = _Operations_EndpointsErrors['i___2fa___register'][keyof _Operations_EndpointsErrors['i___2fa___register']]; export type I2faUpdateKeyRequest = operations['i___2fa___update-key']['requestBody']['content']['application/json']; +export type I2faUpdateKeyErrors = _Operations_EndpointsErrors['i___2fa___update-key'][keyof _Operations_EndpointsErrors['i___2fa___update-key']]; export type I2faRemoveKeyRequest = operations['i___2fa___remove-key']['requestBody']['content']['application/json']; +export type I2faRemoveKeyErrors = _Operations_EndpointsErrors['i___2fa___remove-key'][keyof _Operations_EndpointsErrors['i___2fa___remove-key']]; export type I2faUnregisterRequest = operations['i___2fa___unregister']['requestBody']['content']['application/json']; +export type I2faUnregisterErrors = _Operations_EndpointsErrors['i___2fa___unregister'][keyof _Operations_EndpointsErrors['i___2fa___unregister']]; export type IAppsRequest = operations['i___apps']['requestBody']['content']['application/json']; export type IAppsResponse = operations['i___apps']['responses']['200']['content']['application/json']; +export type IAppsErrors = _Operations_EndpointsErrors['i___apps'][keyof _Operations_EndpointsErrors['i___apps']]; export type IAuthorizedAppsRequest = operations['i___authorized-apps']['requestBody']['content']['application/json']; export type IAuthorizedAppsResponse = operations['i___authorized-apps']['responses']['200']['content']['application/json']; +export type IAuthorizedAppsErrors = _Operations_EndpointsErrors['i___authorized-apps'][keyof _Operations_EndpointsErrors['i___authorized-apps']]; export type IClaimAchievementRequest = operations['i___claim-achievement']['requestBody']['content']['application/json']; +export type IClaimAchievementErrors = _Operations_EndpointsErrors['i___claim-achievement'][keyof _Operations_EndpointsErrors['i___claim-achievement']]; export type IChangePasswordRequest = operations['i___change-password']['requestBody']['content']['application/json']; +export type IChangePasswordErrors = _Operations_EndpointsErrors['i___change-password'][keyof _Operations_EndpointsErrors['i___change-password']]; export type IDeleteAccountRequest = operations['i___delete-account']['requestBody']['content']['application/json']; +export type IDeleteAccountErrors = _Operations_EndpointsErrors['i___delete-account'][keyof _Operations_EndpointsErrors['i___delete-account']]; +export type IExportBlockingErrors = _Operations_EndpointsErrors['i___export-blocking'][keyof _Operations_EndpointsErrors['i___export-blocking']]; export type IExportFollowingRequest = operations['i___export-following']['requestBody']['content']['application/json']; +export type IExportFollowingErrors = _Operations_EndpointsErrors['i___export-following'][keyof _Operations_EndpointsErrors['i___export-following']]; +export type IExportMuteErrors = _Operations_EndpointsErrors['i___export-mute'][keyof _Operations_EndpointsErrors['i___export-mute']]; +export type IExportNotesErrors = _Operations_EndpointsErrors['i___export-notes'][keyof _Operations_EndpointsErrors['i___export-notes']]; +export type IExportClipsErrors = _Operations_EndpointsErrors['i___export-clips'][keyof _Operations_EndpointsErrors['i___export-clips']]; +export type IExportFavoritesErrors = _Operations_EndpointsErrors['i___export-favorites'][keyof _Operations_EndpointsErrors['i___export-favorites']]; +export type IExportUserListsErrors = _Operations_EndpointsErrors['i___export-user-lists'][keyof _Operations_EndpointsErrors['i___export-user-lists']]; +export type IExportAntennasErrors = _Operations_EndpointsErrors['i___export-antennas'][keyof _Operations_EndpointsErrors['i___export-antennas']]; export type IFavoritesRequest = operations['i___favorites']['requestBody']['content']['application/json']; export type IFavoritesResponse = operations['i___favorites']['responses']['200']['content']['application/json']; +export type IFavoritesErrors = _Operations_EndpointsErrors['i___favorites'][keyof _Operations_EndpointsErrors['i___favorites']]; export type IGalleryLikesRequest = operations['i___gallery___likes']['requestBody']['content']['application/json']; export type IGalleryLikesResponse = operations['i___gallery___likes']['responses']['200']['content']['application/json']; +export type IGalleryLikesErrors = _Operations_EndpointsErrors['i___gallery___likes'][keyof _Operations_EndpointsErrors['i___gallery___likes']]; export type IGalleryPostsRequest = operations['i___gallery___posts']['requestBody']['content']['application/json']; export type IGalleryPostsResponse = operations['i___gallery___posts']['responses']['200']['content']['application/json']; +export type IGalleryPostsErrors = _Operations_EndpointsErrors['i___gallery___posts'][keyof _Operations_EndpointsErrors['i___gallery___posts']]; export type IImportBlockingRequest = operations['i___import-blocking']['requestBody']['content']['application/json']; +export type IImportBlockingErrors = _Operations_EndpointsErrors['i___import-blocking'][keyof _Operations_EndpointsErrors['i___import-blocking']]; export type IImportFollowingRequest = operations['i___import-following']['requestBody']['content']['application/json']; +export type IImportFollowingErrors = _Operations_EndpointsErrors['i___import-following'][keyof _Operations_EndpointsErrors['i___import-following']]; export type IImportMutingRequest = operations['i___import-muting']['requestBody']['content']['application/json']; +export type IImportMutingErrors = _Operations_EndpointsErrors['i___import-muting'][keyof _Operations_EndpointsErrors['i___import-muting']]; export type IImportUserListsRequest = operations['i___import-user-lists']['requestBody']['content']['application/json']; +export type IImportUserListsErrors = _Operations_EndpointsErrors['i___import-user-lists'][keyof _Operations_EndpointsErrors['i___import-user-lists']]; export type IImportAntennasRequest = operations['i___import-antennas']['requestBody']['content']['application/json']; +export type IImportAntennasErrors = _Operations_EndpointsErrors['i___import-antennas'][keyof _Operations_EndpointsErrors['i___import-antennas']]; export type INotificationsRequest = operations['i___notifications']['requestBody']['content']['application/json']; export type INotificationsResponse = operations['i___notifications']['responses']['200']['content']['application/json']; +export type INotificationsErrors = _Operations_EndpointsErrors['i___notifications'][keyof _Operations_EndpointsErrors['i___notifications']]; export type INotificationsGroupedRequest = operations['i___notifications-grouped']['requestBody']['content']['application/json']; export type INotificationsGroupedResponse = operations['i___notifications-grouped']['responses']['200']['content']['application/json']; +export type INotificationsGroupedErrors = _Operations_EndpointsErrors['i___notifications-grouped'][keyof _Operations_EndpointsErrors['i___notifications-grouped']]; export type IPageLikesRequest = operations['i___page-likes']['requestBody']['content']['application/json']; export type IPageLikesResponse = operations['i___page-likes']['responses']['200']['content']['application/json']; +export type IPageLikesErrors = _Operations_EndpointsErrors['i___page-likes'][keyof _Operations_EndpointsErrors['i___page-likes']]; export type IPagesRequest = operations['i___pages']['requestBody']['content']['application/json']; export type IPagesResponse = operations['i___pages']['responses']['200']['content']['application/json']; +export type IPagesErrors = _Operations_EndpointsErrors['i___pages'][keyof _Operations_EndpointsErrors['i___pages']]; export type IPinRequest = operations['i___pin']['requestBody']['content']['application/json']; export type IPinResponse = operations['i___pin']['responses']['200']['content']['application/json']; +export type IPinErrors = _Operations_EndpointsErrors['i___pin'][keyof _Operations_EndpointsErrors['i___pin']]; +export type IReadAllUnreadNotesErrors = _Operations_EndpointsErrors['i___read-all-unread-notes'][keyof _Operations_EndpointsErrors['i___read-all-unread-notes']]; export type IReadAnnouncementRequest = operations['i___read-announcement']['requestBody']['content']['application/json']; +export type IReadAnnouncementErrors = _Operations_EndpointsErrors['i___read-announcement'][keyof _Operations_EndpointsErrors['i___read-announcement']]; export type IRegenerateTokenRequest = operations['i___regenerate-token']['requestBody']['content']['application/json']; +export type IRegenerateTokenErrors = _Operations_EndpointsErrors['i___regenerate-token'][keyof _Operations_EndpointsErrors['i___regenerate-token']]; export type IRegistryGetAllRequest = operations['i___registry___get-all']['requestBody']['content']['application/json']; export type IRegistryGetAllResponse = operations['i___registry___get-all']['responses']['200']['content']['application/json']; +export type IRegistryGetAllErrors = _Operations_EndpointsErrors['i___registry___get-all'][keyof _Operations_EndpointsErrors['i___registry___get-all']]; export type IRegistryGetDetailRequest = operations['i___registry___get-detail']['requestBody']['content']['application/json']; export type IRegistryGetDetailResponse = operations['i___registry___get-detail']['responses']['200']['content']['application/json']; +export type IRegistryGetDetailErrors = _Operations_EndpointsErrors['i___registry___get-detail'][keyof _Operations_EndpointsErrors['i___registry___get-detail']]; export type IRegistryGetRequest = operations['i___registry___get']['requestBody']['content']['application/json']; export type IRegistryGetResponse = operations['i___registry___get']['responses']['200']['content']['application/json']; +export type IRegistryGetErrors = _Operations_EndpointsErrors['i___registry___get'][keyof _Operations_EndpointsErrors['i___registry___get']]; export type IRegistryKeysWithTypeRequest = operations['i___registry___keys-with-type']['requestBody']['content']['application/json']; export type IRegistryKeysWithTypeResponse = operations['i___registry___keys-with-type']['responses']['200']['content']['application/json']; +export type IRegistryKeysWithTypeErrors = _Operations_EndpointsErrors['i___registry___keys-with-type'][keyof _Operations_EndpointsErrors['i___registry___keys-with-type']]; export type IRegistryKeysRequest = operations['i___registry___keys']['requestBody']['content']['application/json']; export type IRegistryKeysResponse = operations['i___registry___keys']['responses']['200']['content']['application/json']; +export type IRegistryKeysErrors = _Operations_EndpointsErrors['i___registry___keys'][keyof _Operations_EndpointsErrors['i___registry___keys']]; export type IRegistryRemoveRequest = operations['i___registry___remove']['requestBody']['content']['application/json']; +export type IRegistryRemoveErrors = _Operations_EndpointsErrors['i___registry___remove'][keyof _Operations_EndpointsErrors['i___registry___remove']]; export type IRegistryScopesWithDomainResponse = operations['i___registry___scopes-with-domain']['responses']['200']['content']['application/json']; +export type IRegistryScopesWithDomainErrors = _Operations_EndpointsErrors['i___registry___scopes-with-domain'][keyof _Operations_EndpointsErrors['i___registry___scopes-with-domain']]; export type IRegistrySetRequest = operations['i___registry___set']['requestBody']['content']['application/json']; +export type IRegistrySetErrors = _Operations_EndpointsErrors['i___registry___set'][keyof _Operations_EndpointsErrors['i___registry___set']]; export type IRevokeTokenRequest = operations['i___revoke-token']['requestBody']['content']['application/json']; +export type IRevokeTokenErrors = _Operations_EndpointsErrors['i___revoke-token'][keyof _Operations_EndpointsErrors['i___revoke-token']]; export type ISigninHistoryRequest = operations['i___signin-history']['requestBody']['content']['application/json']; export type ISigninHistoryResponse = operations['i___signin-history']['responses']['200']['content']['application/json']; +export type ISigninHistoryErrors = _Operations_EndpointsErrors['i___signin-history'][keyof _Operations_EndpointsErrors['i___signin-history']]; export type IUnpinRequest = operations['i___unpin']['requestBody']['content']['application/json']; export type IUnpinResponse = operations['i___unpin']['responses']['200']['content']['application/json']; +export type IUnpinErrors = _Operations_EndpointsErrors['i___unpin'][keyof _Operations_EndpointsErrors['i___unpin']]; export type IUpdateEmailRequest = operations['i___update-email']['requestBody']['content']['application/json']; export type IUpdateEmailResponse = operations['i___update-email']['responses']['200']['content']['application/json']; +export type IUpdateEmailErrors = _Operations_EndpointsErrors['i___update-email'][keyof _Operations_EndpointsErrors['i___update-email']]; export type IUpdateRequest = operations['i___update']['requestBody']['content']['application/json']; export type IUpdateResponse = operations['i___update']['responses']['200']['content']['application/json']; +export type IUpdateErrors = _Operations_EndpointsErrors['i___update'][keyof _Operations_EndpointsErrors['i___update']]; export type IMoveRequest = operations['i___move']['requestBody']['content']['application/json']; export type IMoveResponse = operations['i___move']['responses']['200']['content']['application/json']; +export type IMoveErrors = _Operations_EndpointsErrors['i___move'][keyof _Operations_EndpointsErrors['i___move']]; export type IWebhooksCreateRequest = operations['i___webhooks___create']['requestBody']['content']['application/json']; export type IWebhooksCreateResponse = operations['i___webhooks___create']['responses']['200']['content']['application/json']; +export type IWebhooksCreateErrors = _Operations_EndpointsErrors['i___webhooks___create'][keyof _Operations_EndpointsErrors['i___webhooks___create']]; export type IWebhooksListResponse = operations['i___webhooks___list']['responses']['200']['content']['application/json']; +export type IWebhooksListErrors = _Operations_EndpointsErrors['i___webhooks___list'][keyof _Operations_EndpointsErrors['i___webhooks___list']]; export type IWebhooksShowRequest = operations['i___webhooks___show']['requestBody']['content']['application/json']; export type IWebhooksShowResponse = operations['i___webhooks___show']['responses']['200']['content']['application/json']; +export type IWebhooksShowErrors = _Operations_EndpointsErrors['i___webhooks___show'][keyof _Operations_EndpointsErrors['i___webhooks___show']]; export type IWebhooksUpdateRequest = operations['i___webhooks___update']['requestBody']['content']['application/json']; +export type IWebhooksUpdateErrors = _Operations_EndpointsErrors['i___webhooks___update'][keyof _Operations_EndpointsErrors['i___webhooks___update']]; export type IWebhooksDeleteRequest = operations['i___webhooks___delete']['requestBody']['content']['application/json']; +export type IWebhooksDeleteErrors = _Operations_EndpointsErrors['i___webhooks___delete'][keyof _Operations_EndpointsErrors['i___webhooks___delete']]; export type InviteCreateResponse = operations['invite___create']['responses']['200']['content']['application/json']; +export type InviteCreateErrors = _Operations_EndpointsErrors['invite___create'][keyof _Operations_EndpointsErrors['invite___create']]; export type InviteDeleteRequest = operations['invite___delete']['requestBody']['content']['application/json']; +export type InviteDeleteErrors = _Operations_EndpointsErrors['invite___delete'][keyof _Operations_EndpointsErrors['invite___delete']]; export type InviteListRequest = operations['invite___list']['requestBody']['content']['application/json']; export type InviteListResponse = operations['invite___list']['responses']['200']['content']['application/json']; +export type InviteListErrors = _Operations_EndpointsErrors['invite___list'][keyof _Operations_EndpointsErrors['invite___list']]; export type InviteLimitResponse = operations['invite___limit']['responses']['200']['content']['application/json']; +export type InviteLimitErrors = _Operations_EndpointsErrors['invite___limit'][keyof _Operations_EndpointsErrors['invite___limit']]; export type MetaRequest = operations['meta']['requestBody']['content']['application/json']; export type MetaResponse = operations['meta']['responses']['200']['content']['application/json']; +export type MetaErrors = _Operations_EndpointsErrors['meta'][keyof _Operations_EndpointsErrors['meta']]; export type EmojisResponse = operations['emojis']['responses']['200']['content']['application/json']; +export type EmojisErrors = _Operations_EndpointsErrors['emojis'][keyof _Operations_EndpointsErrors['emojis']]; export type EmojiRequest = operations['emoji']['requestBody']['content']['application/json']; export type EmojiResponse = operations['emoji']['responses']['200']['content']['application/json']; +export type EmojiErrors = _Operations_EndpointsErrors['emoji'][keyof _Operations_EndpointsErrors['emoji']]; export type MiauthGenTokenRequest = operations['miauth___gen-token']['requestBody']['content']['application/json']; export type MiauthGenTokenResponse = operations['miauth___gen-token']['responses']['200']['content']['application/json']; +export type MiauthGenTokenErrors = _Operations_EndpointsErrors['miauth___gen-token'][keyof _Operations_EndpointsErrors['miauth___gen-token']]; export type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json']; +export type MuteCreateErrors = _Operations_EndpointsErrors['mute___create'][keyof _Operations_EndpointsErrors['mute___create']]; export type MuteDeleteRequest = operations['mute___delete']['requestBody']['content']['application/json']; +export type MuteDeleteErrors = _Operations_EndpointsErrors['mute___delete'][keyof _Operations_EndpointsErrors['mute___delete']]; export type MuteListRequest = operations['mute___list']['requestBody']['content']['application/json']; export type MuteListResponse = operations['mute___list']['responses']['200']['content']['application/json']; +export type MuteListErrors = _Operations_EndpointsErrors['mute___list'][keyof _Operations_EndpointsErrors['mute___list']]; export type RenoteMuteCreateRequest = operations['renote-mute___create']['requestBody']['content']['application/json']; +export type RenoteMuteCreateErrors = _Operations_EndpointsErrors['renote-mute___create'][keyof _Operations_EndpointsErrors['renote-mute___create']]; export type RenoteMuteDeleteRequest = operations['renote-mute___delete']['requestBody']['content']['application/json']; +export type RenoteMuteDeleteErrors = _Operations_EndpointsErrors['renote-mute___delete'][keyof _Operations_EndpointsErrors['renote-mute___delete']]; export type RenoteMuteListRequest = operations['renote-mute___list']['requestBody']['content']['application/json']; export type RenoteMuteListResponse = operations['renote-mute___list']['responses']['200']['content']['application/json']; +export type RenoteMuteListErrors = _Operations_EndpointsErrors['renote-mute___list'][keyof _Operations_EndpointsErrors['renote-mute___list']]; export type MyAppsRequest = operations['my___apps']['requestBody']['content']['application/json']; export type MyAppsResponse = operations['my___apps']['responses']['200']['content']['application/json']; +export type MyAppsErrors = _Operations_EndpointsErrors['my___apps'][keyof _Operations_EndpointsErrors['my___apps']]; export type NotesRequest = operations['notes']['requestBody']['content']['application/json']; export type NotesResponse = operations['notes']['responses']['200']['content']['application/json']; +export type NotesErrors = _Operations_EndpointsErrors['notes'][keyof _Operations_EndpointsErrors['notes']]; export type NotesChildrenRequest = operations['notes___children']['requestBody']['content']['application/json']; export type NotesChildrenResponse = operations['notes___children']['responses']['200']['content']['application/json']; +export type NotesChildrenErrors = _Operations_EndpointsErrors['notes___children'][keyof _Operations_EndpointsErrors['notes___children']]; export type NotesClipsRequest = operations['notes___clips']['requestBody']['content']['application/json']; export type NotesClipsResponse = operations['notes___clips']['responses']['200']['content']['application/json']; +export type NotesClipsErrors = _Operations_EndpointsErrors['notes___clips'][keyof _Operations_EndpointsErrors['notes___clips']]; export type NotesConversationRequest = operations['notes___conversation']['requestBody']['content']['application/json']; export type NotesConversationResponse = operations['notes___conversation']['responses']['200']['content']['application/json']; +export type NotesConversationErrors = _Operations_EndpointsErrors['notes___conversation'][keyof _Operations_EndpointsErrors['notes___conversation']]; export type NotesCreateRequest = operations['notes___create']['requestBody']['content']['application/json']; export type NotesCreateResponse = operations['notes___create']['responses']['200']['content']['application/json']; +export type NotesCreateErrors = _Operations_EndpointsErrors['notes___create'][keyof _Operations_EndpointsErrors['notes___create']]; export type NotesDeleteRequest = operations['notes___delete']['requestBody']['content']['application/json']; +export type NotesDeleteErrors = _Operations_EndpointsErrors['notes___delete'][keyof _Operations_EndpointsErrors['notes___delete']]; export type NotesFavoritesCreateRequest = operations['notes___favorites___create']['requestBody']['content']['application/json']; +export type NotesFavoritesCreateErrors = _Operations_EndpointsErrors['notes___favorites___create'][keyof _Operations_EndpointsErrors['notes___favorites___create']]; export type NotesFavoritesDeleteRequest = operations['notes___favorites___delete']['requestBody']['content']['application/json']; +export type NotesFavoritesDeleteErrors = _Operations_EndpointsErrors['notes___favorites___delete'][keyof _Operations_EndpointsErrors['notes___favorites___delete']]; export type NotesFeaturedRequest = operations['notes___featured']['requestBody']['content']['application/json']; export type NotesFeaturedResponse = operations['notes___featured']['responses']['200']['content']['application/json']; +export type NotesFeaturedErrors = _Operations_EndpointsErrors['notes___featured'][keyof _Operations_EndpointsErrors['notes___featured']]; export type NotesGlobalTimelineRequest = operations['notes___global-timeline']['requestBody']['content']['application/json']; export type NotesGlobalTimelineResponse = operations['notes___global-timeline']['responses']['200']['content']['application/json']; +export type NotesGlobalTimelineErrors = _Operations_EndpointsErrors['notes___global-timeline'][keyof _Operations_EndpointsErrors['notes___global-timeline']]; export type NotesHybridTimelineRequest = operations['notes___hybrid-timeline']['requestBody']['content']['application/json']; export type NotesHybridTimelineResponse = operations['notes___hybrid-timeline']['responses']['200']['content']['application/json']; +export type NotesHybridTimelineErrors = _Operations_EndpointsErrors['notes___hybrid-timeline'][keyof _Operations_EndpointsErrors['notes___hybrid-timeline']]; export type NotesLocalTimelineRequest = operations['notes___local-timeline']['requestBody']['content']['application/json']; export type NotesLocalTimelineResponse = operations['notes___local-timeline']['responses']['200']['content']['application/json']; +export type NotesLocalTimelineErrors = _Operations_EndpointsErrors['notes___local-timeline'][keyof _Operations_EndpointsErrors['notes___local-timeline']]; export type NotesMentionsRequest = operations['notes___mentions']['requestBody']['content']['application/json']; export type NotesMentionsResponse = operations['notes___mentions']['responses']['200']['content']['application/json']; +export type NotesMentionsErrors = _Operations_EndpointsErrors['notes___mentions'][keyof _Operations_EndpointsErrors['notes___mentions']]; export type NotesPollsRecommendationRequest = operations['notes___polls___recommendation']['requestBody']['content']['application/json']; export type NotesPollsRecommendationResponse = operations['notes___polls___recommendation']['responses']['200']['content']['application/json']; +export type NotesPollsRecommendationErrors = _Operations_EndpointsErrors['notes___polls___recommendation'][keyof _Operations_EndpointsErrors['notes___polls___recommendation']]; export type NotesPollsVoteRequest = operations['notes___polls___vote']['requestBody']['content']['application/json']; +export type NotesPollsVoteErrors = _Operations_EndpointsErrors['notes___polls___vote'][keyof _Operations_EndpointsErrors['notes___polls___vote']]; export type NotesReactionsRequest = operations['notes___reactions']['requestBody']['content']['application/json']; export type NotesReactionsResponse = operations['notes___reactions']['responses']['200']['content']['application/json']; +export type NotesReactionsErrors = _Operations_EndpointsErrors['notes___reactions'][keyof _Operations_EndpointsErrors['notes___reactions']]; export type NotesReactionsCreateRequest = operations['notes___reactions___create']['requestBody']['content']['application/json']; +export type NotesReactionsCreateErrors = _Operations_EndpointsErrors['notes___reactions___create'][keyof _Operations_EndpointsErrors['notes___reactions___create']]; export type NotesReactionsDeleteRequest = operations['notes___reactions___delete']['requestBody']['content']['application/json']; +export type NotesReactionsDeleteErrors = _Operations_EndpointsErrors['notes___reactions___delete'][keyof _Operations_EndpointsErrors['notes___reactions___delete']]; export type NotesRenotesRequest = operations['notes___renotes']['requestBody']['content']['application/json']; export type NotesRenotesResponse = operations['notes___renotes']['responses']['200']['content']['application/json']; +export type NotesRenotesErrors = _Operations_EndpointsErrors['notes___renotes'][keyof _Operations_EndpointsErrors['notes___renotes']]; export type NotesRepliesRequest = operations['notes___replies']['requestBody']['content']['application/json']; export type NotesRepliesResponse = operations['notes___replies']['responses']['200']['content']['application/json']; +export type NotesRepliesErrors = _Operations_EndpointsErrors['notes___replies'][keyof _Operations_EndpointsErrors['notes___replies']]; export type NotesSearchByTagRequest = operations['notes___search-by-tag']['requestBody']['content']['application/json']; export type NotesSearchByTagResponse = operations['notes___search-by-tag']['responses']['200']['content']['application/json']; +export type NotesSearchByTagErrors = _Operations_EndpointsErrors['notes___search-by-tag'][keyof _Operations_EndpointsErrors['notes___search-by-tag']]; export type NotesSearchRequest = operations['notes___search']['requestBody']['content']['application/json']; export type NotesSearchResponse = operations['notes___search']['responses']['200']['content']['application/json']; +export type NotesSearchErrors = _Operations_EndpointsErrors['notes___search'][keyof _Operations_EndpointsErrors['notes___search']]; export type NotesShowRequest = operations['notes___show']['requestBody']['content']['application/json']; export type NotesShowResponse = operations['notes___show']['responses']['200']['content']['application/json']; +export type NotesShowErrors = _Operations_EndpointsErrors['notes___show'][keyof _Operations_EndpointsErrors['notes___show']]; export type NotesStateRequest = operations['notes___state']['requestBody']['content']['application/json']; export type NotesStateResponse = operations['notes___state']['responses']['200']['content']['application/json']; +export type NotesStateErrors = _Operations_EndpointsErrors['notes___state'][keyof _Operations_EndpointsErrors['notes___state']]; export type NotesThreadMutingCreateRequest = operations['notes___thread-muting___create']['requestBody']['content']['application/json']; +export type NotesThreadMutingCreateErrors = _Operations_EndpointsErrors['notes___thread-muting___create'][keyof _Operations_EndpointsErrors['notes___thread-muting___create']]; export type NotesThreadMutingDeleteRequest = operations['notes___thread-muting___delete']['requestBody']['content']['application/json']; +export type NotesThreadMutingDeleteErrors = _Operations_EndpointsErrors['notes___thread-muting___delete'][keyof _Operations_EndpointsErrors['notes___thread-muting___delete']]; export type NotesTimelineRequest = operations['notes___timeline']['requestBody']['content']['application/json']; export type NotesTimelineResponse = operations['notes___timeline']['responses']['200']['content']['application/json']; +export type NotesTimelineErrors = _Operations_EndpointsErrors['notes___timeline'][keyof _Operations_EndpointsErrors['notes___timeline']]; export type NotesTranslateRequest = operations['notes___translate']['requestBody']['content']['application/json']; export type NotesTranslateResponse = operations['notes___translate']['responses']['200']['content']['application/json']; +export type NotesTranslateErrors = _Operations_EndpointsErrors['notes___translate'][keyof _Operations_EndpointsErrors['notes___translate']]; export type NotesUnrenoteRequest = operations['notes___unrenote']['requestBody']['content']['application/json']; +export type NotesUnrenoteErrors = _Operations_EndpointsErrors['notes___unrenote'][keyof _Operations_EndpointsErrors['notes___unrenote']]; export type NotesUserListTimelineRequest = operations['notes___user-list-timeline']['requestBody']['content']['application/json']; export type NotesUserListTimelineResponse = operations['notes___user-list-timeline']['responses']['200']['content']['application/json']; +export type NotesUserListTimelineErrors = _Operations_EndpointsErrors['notes___user-list-timeline'][keyof _Operations_EndpointsErrors['notes___user-list-timeline']]; export type NotificationsCreateRequest = operations['notifications___create']['requestBody']['content']['application/json']; +export type NotificationsCreateErrors = _Operations_EndpointsErrors['notifications___create'][keyof _Operations_EndpointsErrors['notifications___create']]; +export type NotificationsFlushErrors = _Operations_EndpointsErrors['notifications___flush'][keyof _Operations_EndpointsErrors['notifications___flush']]; +export type NotificationsMarkAllAsReadErrors = _Operations_EndpointsErrors['notifications___mark-all-as-read'][keyof _Operations_EndpointsErrors['notifications___mark-all-as-read']]; +export type NotificationsTestNotificationErrors = _Operations_EndpointsErrors['notifications___test-notification'][keyof _Operations_EndpointsErrors['notifications___test-notification']]; export type PagePushRequest = operations['page-push']['requestBody']['content']['application/json']; +export type PagePushErrors = _Operations_EndpointsErrors['page-push'][keyof _Operations_EndpointsErrors['page-push']]; export type PagesCreateRequest = operations['pages___create']['requestBody']['content']['application/json']; export type PagesCreateResponse = operations['pages___create']['responses']['200']['content']['application/json']; +export type PagesCreateErrors = _Operations_EndpointsErrors['pages___create'][keyof _Operations_EndpointsErrors['pages___create']]; export type PagesDeleteRequest = operations['pages___delete']['requestBody']['content']['application/json']; +export type PagesDeleteErrors = _Operations_EndpointsErrors['pages___delete'][keyof _Operations_EndpointsErrors['pages___delete']]; export type PagesFeaturedResponse = operations['pages___featured']['responses']['200']['content']['application/json']; +export type PagesFeaturedErrors = _Operations_EndpointsErrors['pages___featured'][keyof _Operations_EndpointsErrors['pages___featured']]; export type PagesLikeRequest = operations['pages___like']['requestBody']['content']['application/json']; +export type PagesLikeErrors = _Operations_EndpointsErrors['pages___like'][keyof _Operations_EndpointsErrors['pages___like']]; export type PagesShowRequest = operations['pages___show']['requestBody']['content']['application/json']; export type PagesShowResponse = operations['pages___show']['responses']['200']['content']['application/json']; +export type PagesShowErrors = _Operations_EndpointsErrors['pages___show'][keyof _Operations_EndpointsErrors['pages___show']]; export type PagesUnlikeRequest = operations['pages___unlike']['requestBody']['content']['application/json']; +export type PagesUnlikeErrors = _Operations_EndpointsErrors['pages___unlike'][keyof _Operations_EndpointsErrors['pages___unlike']]; export type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json']; +export type PagesUpdateErrors = _Operations_EndpointsErrors['pages___update'][keyof _Operations_EndpointsErrors['pages___update']]; export type FlashCreateRequest = operations['flash___create']['requestBody']['content']['application/json']; export type FlashCreateResponse = operations['flash___create']['responses']['200']['content']['application/json']; +export type FlashCreateErrors = _Operations_EndpointsErrors['flash___create'][keyof _Operations_EndpointsErrors['flash___create']]; export type FlashDeleteRequest = operations['flash___delete']['requestBody']['content']['application/json']; +export type FlashDeleteErrors = _Operations_EndpointsErrors['flash___delete'][keyof _Operations_EndpointsErrors['flash___delete']]; export type FlashFeaturedResponse = operations['flash___featured']['responses']['200']['content']['application/json']; +export type FlashFeaturedErrors = _Operations_EndpointsErrors['flash___featured'][keyof _Operations_EndpointsErrors['flash___featured']]; export type FlashLikeRequest = operations['flash___like']['requestBody']['content']['application/json']; +export type FlashLikeErrors = _Operations_EndpointsErrors['flash___like'][keyof _Operations_EndpointsErrors['flash___like']]; export type FlashShowRequest = operations['flash___show']['requestBody']['content']['application/json']; export type FlashShowResponse = operations['flash___show']['responses']['200']['content']['application/json']; +export type FlashShowErrors = _Operations_EndpointsErrors['flash___show'][keyof _Operations_EndpointsErrors['flash___show']]; export type FlashUnlikeRequest = operations['flash___unlike']['requestBody']['content']['application/json']; +export type FlashUnlikeErrors = _Operations_EndpointsErrors['flash___unlike'][keyof _Operations_EndpointsErrors['flash___unlike']]; export type FlashUpdateRequest = operations['flash___update']['requestBody']['content']['application/json']; +export type FlashUpdateErrors = _Operations_EndpointsErrors['flash___update'][keyof _Operations_EndpointsErrors['flash___update']]; export type FlashMyRequest = operations['flash___my']['requestBody']['content']['application/json']; export type FlashMyResponse = operations['flash___my']['responses']['200']['content']['application/json']; +export type FlashMyErrors = _Operations_EndpointsErrors['flash___my'][keyof _Operations_EndpointsErrors['flash___my']]; export type FlashMyLikesRequest = operations['flash___my-likes']['requestBody']['content']['application/json']; export type FlashMyLikesResponse = operations['flash___my-likes']['responses']['200']['content']['application/json']; +export type FlashMyLikesErrors = _Operations_EndpointsErrors['flash___my-likes'][keyof _Operations_EndpointsErrors['flash___my-likes']]; export type PingResponse = operations['ping']['responses']['200']['content']['application/json']; +export type PingErrors = _Operations_EndpointsErrors['ping'][keyof _Operations_EndpointsErrors['ping']]; export type PinnedUsersResponse = operations['pinned-users']['responses']['200']['content']['application/json']; +export type PinnedUsersErrors = _Operations_EndpointsErrors['pinned-users'][keyof _Operations_EndpointsErrors['pinned-users']]; export type PromoReadRequest = operations['promo___read']['requestBody']['content']['application/json']; +export type PromoReadErrors = _Operations_EndpointsErrors['promo___read'][keyof _Operations_EndpointsErrors['promo___read']]; export type RolesListResponse = operations['roles___list']['responses']['200']['content']['application/json']; +export type RolesListErrors = _Operations_EndpointsErrors['roles___list'][keyof _Operations_EndpointsErrors['roles___list']]; export type RolesShowRequest = operations['roles___show']['requestBody']['content']['application/json']; export type RolesShowResponse = operations['roles___show']['responses']['200']['content']['application/json']; +export type RolesShowErrors = _Operations_EndpointsErrors['roles___show'][keyof _Operations_EndpointsErrors['roles___show']]; export type RolesUsersRequest = operations['roles___users']['requestBody']['content']['application/json']; export type RolesUsersResponse = operations['roles___users']['responses']['200']['content']['application/json']; +export type RolesUsersErrors = _Operations_EndpointsErrors['roles___users'][keyof _Operations_EndpointsErrors['roles___users']]; export type RolesNotesRequest = operations['roles___notes']['requestBody']['content']['application/json']; export type RolesNotesResponse = operations['roles___notes']['responses']['200']['content']['application/json']; +export type RolesNotesErrors = _Operations_EndpointsErrors['roles___notes'][keyof _Operations_EndpointsErrors['roles___notes']]; export type RequestResetPasswordRequest = operations['request-reset-password']['requestBody']['content']['application/json']; +export type RequestResetPasswordErrors = _Operations_EndpointsErrors['request-reset-password'][keyof _Operations_EndpointsErrors['request-reset-password']]; +export type ResetDbErrors = _Operations_EndpointsErrors['reset-db'][keyof _Operations_EndpointsErrors['reset-db']]; export type ResetPasswordRequest = operations['reset-password']['requestBody']['content']['application/json']; +export type ResetPasswordErrors = _Operations_EndpointsErrors['reset-password'][keyof _Operations_EndpointsErrors['reset-password']]; export type ServerInfoResponse = operations['server-info']['responses']['200']['content']['application/json']; +export type ServerInfoErrors = _Operations_EndpointsErrors['server-info'][keyof _Operations_EndpointsErrors['server-info']]; export type StatsResponse = operations['stats']['responses']['200']['content']['application/json']; +export type StatsErrors = _Operations_EndpointsErrors['stats'][keyof _Operations_EndpointsErrors['stats']]; export type SwShowRegistrationRequest = operations['sw___show-registration']['requestBody']['content']['application/json']; export type SwShowRegistrationResponse = operations['sw___show-registration']['responses']['200']['content']['application/json']; +export type SwShowRegistrationErrors = _Operations_EndpointsErrors['sw___show-registration'][keyof _Operations_EndpointsErrors['sw___show-registration']]; export type SwUpdateRegistrationRequest = operations['sw___update-registration']['requestBody']['content']['application/json']; export type SwUpdateRegistrationResponse = operations['sw___update-registration']['responses']['200']['content']['application/json']; +export type SwUpdateRegistrationErrors = _Operations_EndpointsErrors['sw___update-registration'][keyof _Operations_EndpointsErrors['sw___update-registration']]; export type SwRegisterRequest = operations['sw___register']['requestBody']['content']['application/json']; export type SwRegisterResponse = operations['sw___register']['responses']['200']['content']['application/json']; +export type SwRegisterErrors = _Operations_EndpointsErrors['sw___register'][keyof _Operations_EndpointsErrors['sw___register']]; export type SwUnregisterRequest = operations['sw___unregister']['requestBody']['content']['application/json']; +export type SwUnregisterErrors = _Operations_EndpointsErrors['sw___unregister'][keyof _Operations_EndpointsErrors['sw___unregister']]; export type TestRequest = operations['test']['requestBody']['content']['application/json']; export type TestResponse = operations['test']['responses']['200']['content']['application/json']; +export type TestErrors = _Operations_EndpointsErrors['test'][keyof _Operations_EndpointsErrors['test']]; export type UsernameAvailableRequest = operations['username___available']['requestBody']['content']['application/json']; export type UsernameAvailableResponse = operations['username___available']['responses']['200']['content']['application/json']; +export type UsernameAvailableErrors = _Operations_EndpointsErrors['username___available'][keyof _Operations_EndpointsErrors['username___available']]; export type UsersRequest = operations['users']['requestBody']['content']['application/json']; export type UsersResponse = operations['users']['responses']['200']['content']['application/json']; +export type UsersErrors = _Operations_EndpointsErrors['users'][keyof _Operations_EndpointsErrors['users']]; export type UsersClipsRequest = operations['users___clips']['requestBody']['content']['application/json']; export type UsersClipsResponse = operations['users___clips']['responses']['200']['content']['application/json']; +export type UsersClipsErrors = _Operations_EndpointsErrors['users___clips'][keyof _Operations_EndpointsErrors['users___clips']]; export type UsersFollowersRequest = operations['users___followers']['requestBody']['content']['application/json']; export type UsersFollowersResponse = operations['users___followers']['responses']['200']['content']['application/json']; +export type UsersFollowersErrors = _Operations_EndpointsErrors['users___followers'][keyof _Operations_EndpointsErrors['users___followers']]; export type UsersFollowingRequest = operations['users___following']['requestBody']['content']['application/json']; export type UsersFollowingResponse = operations['users___following']['responses']['200']['content']['application/json']; +export type UsersFollowingErrors = _Operations_EndpointsErrors['users___following'][keyof _Operations_EndpointsErrors['users___following']]; export type UsersGalleryPostsRequest = operations['users___gallery___posts']['requestBody']['content']['application/json']; export type UsersGalleryPostsResponse = operations['users___gallery___posts']['responses']['200']['content']['application/json']; +export type UsersGalleryPostsErrors = _Operations_EndpointsErrors['users___gallery___posts'][keyof _Operations_EndpointsErrors['users___gallery___posts']]; export type UsersGetFrequentlyRepliedUsersRequest = operations['users___get-frequently-replied-users']['requestBody']['content']['application/json']; export type UsersGetFrequentlyRepliedUsersResponse = operations['users___get-frequently-replied-users']['responses']['200']['content']['application/json']; +export type UsersGetFrequentlyRepliedUsersErrors = _Operations_EndpointsErrors['users___get-frequently-replied-users'][keyof _Operations_EndpointsErrors['users___get-frequently-replied-users']]; export type UsersFeaturedNotesRequest = operations['users___featured-notes']['requestBody']['content']['application/json']; export type UsersFeaturedNotesResponse = operations['users___featured-notes']['responses']['200']['content']['application/json']; +export type UsersFeaturedNotesErrors = _Operations_EndpointsErrors['users___featured-notes'][keyof _Operations_EndpointsErrors['users___featured-notes']]; export type UsersListsCreateRequest = operations['users___lists___create']['requestBody']['content']['application/json']; export type UsersListsCreateResponse = operations['users___lists___create']['responses']['200']['content']['application/json']; +export type UsersListsCreateErrors = _Operations_EndpointsErrors['users___lists___create'][keyof _Operations_EndpointsErrors['users___lists___create']]; export type UsersListsDeleteRequest = operations['users___lists___delete']['requestBody']['content']['application/json']; +export type UsersListsDeleteErrors = _Operations_EndpointsErrors['users___lists___delete'][keyof _Operations_EndpointsErrors['users___lists___delete']]; export type UsersListsListRequest = operations['users___lists___list']['requestBody']['content']['application/json']; export type UsersListsListResponse = operations['users___lists___list']['responses']['200']['content']['application/json']; +export type UsersListsListErrors = _Operations_EndpointsErrors['users___lists___list'][keyof _Operations_EndpointsErrors['users___lists___list']]; export type UsersListsPullRequest = operations['users___lists___pull']['requestBody']['content']['application/json']; +export type UsersListsPullErrors = _Operations_EndpointsErrors['users___lists___pull'][keyof _Operations_EndpointsErrors['users___lists___pull']]; export type UsersListsPushRequest = operations['users___lists___push']['requestBody']['content']['application/json']; +export type UsersListsPushErrors = _Operations_EndpointsErrors['users___lists___push'][keyof _Operations_EndpointsErrors['users___lists___push']]; export type UsersListsShowRequest = operations['users___lists___show']['requestBody']['content']['application/json']; export type UsersListsShowResponse = operations['users___lists___show']['responses']['200']['content']['application/json']; +export type UsersListsShowErrors = _Operations_EndpointsErrors['users___lists___show'][keyof _Operations_EndpointsErrors['users___lists___show']]; export type UsersListsFavoriteRequest = operations['users___lists___favorite']['requestBody']['content']['application/json']; +export type UsersListsFavoriteErrors = _Operations_EndpointsErrors['users___lists___favorite'][keyof _Operations_EndpointsErrors['users___lists___favorite']]; export type UsersListsUnfavoriteRequest = operations['users___lists___unfavorite']['requestBody']['content']['application/json']; +export type UsersListsUnfavoriteErrors = _Operations_EndpointsErrors['users___lists___unfavorite'][keyof _Operations_EndpointsErrors['users___lists___unfavorite']]; export type UsersListsUpdateRequest = operations['users___lists___update']['requestBody']['content']['application/json']; export type UsersListsUpdateResponse = operations['users___lists___update']['responses']['200']['content']['application/json']; +export type UsersListsUpdateErrors = _Operations_EndpointsErrors['users___lists___update'][keyof _Operations_EndpointsErrors['users___lists___update']]; export type UsersListsCreateFromPublicRequest = operations['users___lists___create-from-public']['requestBody']['content']['application/json']; export type UsersListsCreateFromPublicResponse = operations['users___lists___create-from-public']['responses']['200']['content']['application/json']; +export type UsersListsCreateFromPublicErrors = _Operations_EndpointsErrors['users___lists___create-from-public'][keyof _Operations_EndpointsErrors['users___lists___create-from-public']]; export type UsersListsUpdateMembershipRequest = operations['users___lists___update-membership']['requestBody']['content']['application/json']; +export type UsersListsUpdateMembershipErrors = _Operations_EndpointsErrors['users___lists___update-membership'][keyof _Operations_EndpointsErrors['users___lists___update-membership']]; export type UsersListsGetMembershipsRequest = operations['users___lists___get-memberships']['requestBody']['content']['application/json']; export type UsersListsGetMembershipsResponse = operations['users___lists___get-memberships']['responses']['200']['content']['application/json']; +export type UsersListsGetMembershipsErrors = _Operations_EndpointsErrors['users___lists___get-memberships'][keyof _Operations_EndpointsErrors['users___lists___get-memberships']]; export type UsersNotesRequest = operations['users___notes']['requestBody']['content']['application/json']; export type UsersNotesResponse = operations['users___notes']['responses']['200']['content']['application/json']; +export type UsersNotesErrors = _Operations_EndpointsErrors['users___notes'][keyof _Operations_EndpointsErrors['users___notes']]; export type UsersPagesRequest = operations['users___pages']['requestBody']['content']['application/json']; export type UsersPagesResponse = operations['users___pages']['responses']['200']['content']['application/json']; +export type UsersPagesErrors = _Operations_EndpointsErrors['users___pages'][keyof _Operations_EndpointsErrors['users___pages']]; export type UsersFlashsRequest = operations['users___flashs']['requestBody']['content']['application/json']; export type UsersFlashsResponse = operations['users___flashs']['responses']['200']['content']['application/json']; +export type UsersFlashsErrors = _Operations_EndpointsErrors['users___flashs'][keyof _Operations_EndpointsErrors['users___flashs']]; export type UsersReactionsRequest = operations['users___reactions']['requestBody']['content']['application/json']; export type UsersReactionsResponse = operations['users___reactions']['responses']['200']['content']['application/json']; +export type UsersReactionsErrors = _Operations_EndpointsErrors['users___reactions'][keyof _Operations_EndpointsErrors['users___reactions']]; export type UsersRecommendationRequest = operations['users___recommendation']['requestBody']['content']['application/json']; export type UsersRecommendationResponse = operations['users___recommendation']['responses']['200']['content']['application/json']; +export type UsersRecommendationErrors = _Operations_EndpointsErrors['users___recommendation'][keyof _Operations_EndpointsErrors['users___recommendation']]; export type UsersRelationRequest = operations['users___relation']['requestBody']['content']['application/json']; export type UsersRelationResponse = operations['users___relation']['responses']['200']['content']['application/json']; +export type UsersRelationErrors = _Operations_EndpointsErrors['users___relation'][keyof _Operations_EndpointsErrors['users___relation']]; export type UsersReportAbuseRequest = operations['users___report-abuse']['requestBody']['content']['application/json']; +export type UsersReportAbuseErrors = _Operations_EndpointsErrors['users___report-abuse'][keyof _Operations_EndpointsErrors['users___report-abuse']]; export type UsersSearchByUsernameAndHostRequest = operations['users___search-by-username-and-host']['requestBody']['content']['application/json']; export type UsersSearchByUsernameAndHostResponse = operations['users___search-by-username-and-host']['responses']['200']['content']['application/json']; +export type UsersSearchByUsernameAndHostErrors = _Operations_EndpointsErrors['users___search-by-username-and-host'][keyof _Operations_EndpointsErrors['users___search-by-username-and-host']]; export type UsersSearchRequest = operations['users___search']['requestBody']['content']['application/json']; export type UsersSearchResponse = operations['users___search']['responses']['200']['content']['application/json']; +export type UsersSearchErrors = _Operations_EndpointsErrors['users___search'][keyof _Operations_EndpointsErrors['users___search']]; export type UsersShowRequest = operations['users___show']['requestBody']['content']['application/json']; export type UsersShowResponse = operations['users___show']['responses']['200']['content']['application/json']; +export type UsersShowErrors = _Operations_EndpointsErrors['users___show'][keyof _Operations_EndpointsErrors['users___show']]; export type UsersAchievementsRequest = operations['users___achievements']['requestBody']['content']['application/json']; export type UsersAchievementsResponse = operations['users___achievements']['responses']['200']['content']['application/json']; +export type UsersAchievementsErrors = _Operations_EndpointsErrors['users___achievements'][keyof _Operations_EndpointsErrors['users___achievements']]; export type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json']; +export type UsersUpdateMemoErrors = _Operations_EndpointsErrors['users___update-memo'][keyof _Operations_EndpointsErrors['users___update-memo']]; export type FetchRssRequest = operations['fetch-rss']['requestBody']['content']['application/json']; export type FetchRssResponse = operations['fetch-rss']['responses']['200']['content']['application/json']; +export type FetchRssErrors = _Operations_EndpointsErrors['fetch-rss'][keyof _Operations_EndpointsErrors['fetch-rss']]; export type FetchExternalResourcesRequest = operations['fetch-external-resources']['requestBody']['content']['application/json']; export type FetchExternalResourcesResponse = operations['fetch-external-resources']['responses']['200']['content']['application/json']; +export type FetchExternalResourcesErrors = _Operations_EndpointsErrors['fetch-external-resources'][keyof _Operations_EndpointsErrors['fetch-external-resources']]; export type RetentionResponse = operations['retention']['responses']['200']['content']['application/json']; +export type RetentionErrors = _Operations_EndpointsErrors['retention'][keyof _Operations_EndpointsErrors['retention']]; export type BubbleGameRegisterRequest = operations['bubble-game___register']['requestBody']['content']['application/json']; +export type BubbleGameRegisterErrors = _Operations_EndpointsErrors['bubble-game___register'][keyof _Operations_EndpointsErrors['bubble-game___register']]; export type BubbleGameRankingRequest = operations['bubble-game___ranking']['requestBody']['content']['application/json']; export type BubbleGameRankingResponse = operations['bubble-game___ranking']['responses']['200']['content']['application/json']; +export type BubbleGameRankingErrors = _Operations_EndpointsErrors['bubble-game___ranking'][keyof _Operations_EndpointsErrors['bubble-game___ranking']]; export type ReversiCancelMatchRequest = operations['reversi___cancel-match']['requestBody']['content']['application/json']; +export type ReversiCancelMatchErrors = _Operations_EndpointsErrors['reversi___cancel-match'][keyof _Operations_EndpointsErrors['reversi___cancel-match']]; export type ReversiGamesRequest = operations['reversi___games']['requestBody']['content']['application/json']; export type ReversiGamesResponse = operations['reversi___games']['responses']['200']['content']['application/json']; +export type ReversiGamesErrors = _Operations_EndpointsErrors['reversi___games'][keyof _Operations_EndpointsErrors['reversi___games']]; export type ReversiMatchRequest = operations['reversi___match']['requestBody']['content']['application/json']; export type ReversiMatchResponse = operations['reversi___match']['responses']['200']['content']['application/json']; +export type ReversiMatchErrors = _Operations_EndpointsErrors['reversi___match'][keyof _Operations_EndpointsErrors['reversi___match']]; export type ReversiInvitationsResponse = operations['reversi___invitations']['responses']['200']['content']['application/json']; +export type ReversiInvitationsErrors = _Operations_EndpointsErrors['reversi___invitations'][keyof _Operations_EndpointsErrors['reversi___invitations']]; export type ReversiShowGameRequest = operations['reversi___show-game']['requestBody']['content']['application/json']; export type ReversiShowGameResponse = operations['reversi___show-game']['responses']['200']['content']['application/json']; +export type ReversiShowGameErrors = _Operations_EndpointsErrors['reversi___show-game'][keyof _Operations_EndpointsErrors['reversi___show-game']]; export type ReversiSurrenderRequest = operations['reversi___surrender']['requestBody']['content']['application/json']; +export type ReversiSurrenderErrors = _Operations_EndpointsErrors['reversi___surrender'][keyof _Operations_EndpointsErrors['reversi___surrender']]; export type ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json']; export type ReversiVerifyResponse = operations['reversi___verify']['responses']['200']['content']['application/json']; +export type ReversiVerifyErrors = _Operations_EndpointsErrors['reversi___verify'][keyof _Operations_EndpointsErrors['reversi___verify']]; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 7a84cb6a1a..9d12788c01 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -226,6 +226,18 @@ export type SignupPendingResponse = { i: string, }; +export type SignupErrors = { + message: 'DUPLICATED_USERNAME', + code: 400, +} | { + message: 'USED_USERNAME', + code: 400, +} | { + message: 'DENIED_USERNAME', + code: 400, +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +} | Record; + export type SigninRequest = { username: string; password: string; @@ -236,3 +248,21 @@ export type SigninResponse = { id: User['id'], i: string, }; + +export type SigninErrors = { + message: 'Too many failed attempts to sign in. Try again later.', + code: 'TOO_MANY_AUTHENTICATION_FAILURES', + id: '22d05606-fbcf-421a-a2db-b32610dcfd1b', +} | { + id: '6cc579cc-885d-43d8-95c2-b8c7fc963280', // User not found +} | { + id: 'e03a5f46-d309-4865-9b69-56282d94e1eb', // User is suspended +} | { + id: '4e30e80c-e338-45a0-8c8f-44455efa3b76', // Internal server error +} | { + id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c', // Invalid credentials +} | { + id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f', // Invalid one-time password +} | { + id: '93b86c4b-72f9-40eb-9815-798928603d1e', // Invalid passkey credential +}; From 52954539482826573ad7858d28f7b70ad0edb72b Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:39:39 +0900 Subject: [PATCH 02/20] fix lint --- .../misskey-js/generator/src/generator.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 7f21413877..204105d54f 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -96,12 +96,14 @@ async function generateEndpointErrors( const errorResponseCodes = Object.keys(operation.responses).filter((key) => !okResponses.includes(key)); const errorTypes = new Map(); errorResponseCodes.forEach((code) => { - const response = operation.responses![code]; + if (operation.responses == null) return; + const response = operation.responses[code]; if ('content' in response && response.content != null && 'application/json' in response.content) { const errors = response.content['application/json'].examples; if (errors != null) { Object.keys(errors).forEach((key) => { const error = errors[key]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (error != null && 'value' in error && error.value != null) { errorTypes.set(key, error.value); } @@ -270,17 +272,17 @@ async function generateApiClientJSDoc( endpointOutputLine.push(''); endpointOutputLine.push( - `interface IErrPromise {`, - ` then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;`, - ``, - ` catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;`, - `}`, - ``, - `class ErrPromise extends Promise implements IErrPromise {`, - ` constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) {`, - ` super(executor);`, - ` }`, - `}`, + 'interface IErrPromise {', + ' then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;', + '', + ' catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;', + '}', + '', + 'class ErrPromise extends Promise implements IErrPromise {', + ' constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) {', + ' super(executor);', + ' }', + '}', ); endpointOutputLine.push(''); From 9b85a33ab56e807e7b4798a280f9f25716b8efe6 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:40:39 +0900 Subject: [PATCH 03/20] Update Changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a913e42500..69fd95218c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 +### Misskey.js +- Feat: reject時のエラーに型情報を追加 + ## 2024.5.0 ### Note From 883e205555990d6a4e6be21f2cd3f36d3eb3fe30 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:56:16 +0900 Subject: [PATCH 04/20] =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BCID=E3=81=8C?= =?UTF-8?q?=E5=90=8C=E3=81=98=E3=82=82=E3=81=AE=E3=81=AF=E5=85=B1=E9=80=9A?= =?UTF-8?q?=E5=8C=96=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misskey-js/generator/src/generator.ts | 19 +- .../misskey-js/src/autogen/endpointErrors.ts | 4917 +++++++++-------- 2 files changed, 2644 insertions(+), 2292 deletions(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 204105d54f..db8a89c34e 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -14,7 +14,6 @@ async function generateBaseTypes( openApiJsonPath: string, typeFileName: string, ) { - const lines: string[] = []; for (const lint of disabledLints) { lines.push(`/* eslint ${lint}: 0 */`); @@ -76,6 +75,8 @@ async function generateEndpointErrors( } endpointsErrorsOutputLine.push(''); + const errorWithIdTypes = new Map(); + endpointsErrorsOutputLine.push('export type EndpointsErrors = {'); for (const operation of postPathItems) { @@ -94,7 +95,8 @@ async function generateEndpointErrors( ]; const errorResponseCodes = Object.keys(operation.responses).filter((key) => !okResponses.includes(key)); - const errorTypes = new Map(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const errorTypes = new Map>(); errorResponseCodes.forEach((code) => { if (operation.responses == null) return; const response = operation.responses[code]; @@ -118,7 +120,12 @@ async function generateEndpointErrors( if ('error' in value && value.error != null) { let typeString = JSON.stringify(value.error); typeString = typeString.substring(0, typeString.length - 1) + ', [x: string]: any ' + typeString.substring(typeString.length - 1); - endpointsErrorsOutputLine.push(`\t\t'${key}': ${typeString},`); + if ('id' in value.error && value.error.id != null) { + errorWithIdTypes.set(value.error.id, typeString); + endpointsErrorsOutputLine.push(`\t\t'${key}': IdentifiableError['${value.error.id}'],`); + } else { + endpointsErrorsOutputLine.push(`\t\t'${key}': ${typeString},`); + } } } endpointsErrorsOutputLine.push('\t},'); @@ -129,6 +136,12 @@ async function generateEndpointErrors( endpointsErrorsOutputLine.push('};'); endpointsErrorsOutputLine.push(''); + endpointsErrorsOutputLine.push('export type IdentifiableError = {'); + for (const [key, value] of errorWithIdTypes) { + endpointsErrorsOutputLine.push(`\t'${key}': ${value},`); + } + endpointsErrorsOutputLine.push('};'); + await writeFile(endpointErrorsOutputPath, endpointsErrorsOutputLine.join('\n')); } diff --git a/packages/misskey-js/src/autogen/endpointErrors.ts b/packages/misskey-js/src/autogen/endpointErrors.ts index 1631f76d92..29e5eb028f 100644 --- a/packages/misskey-js/src/autogen/endpointErrors.ts +++ b/packages/misskey-js/src/autogen/endpointErrors.ts @@ -3,3050 +3,3389 @@ export type EndpointsErrors = { 'admin___meta': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-user-reports': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-report___notification-recipient___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-report___notification-recipient___show': { - 'NO_SUCH_RECIPIENT': {'message':'No such recipient.', 'code':'NO_SUCH_RECIPIENT', 'id':'013de6a8-f757-04cb-4d73-cc2a7e3368e4', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_RECIPIENT': IdentifiableError['013de6a8-f757-04cb-4d73-cc2a7e3368e4'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-report___notification-recipient___create': { - 'CORRELATION_CHECK_EMAIL': {'message':'If "method" is email, "userId" must be set.', 'code':'CORRELATION_CHECK_EMAIL', 'id':'348bb8ae-575a-6fe9-4327-5811999def8f', 'httpStatusCode':400, [x: string]: any }, - 'CORRELATION_CHECK_WEBHOOK': {'message':'If "method" is webhook, "systemWebhookId" must be set.', 'code':'CORRELATION_CHECK_WEBHOOK', 'id':'b0c15051-de2d-29ef-260c-9585cddd701a', 'httpStatusCode':400, [x: string]: any }, - 'EMAIL_ADDRESS_NOT_SET': {'message':'Email address is not set.', 'code':'EMAIL_ADDRESS_NOT_SET', 'id':'7cc1d85e-2f58-fc31-b644-3de8d0d3421f', 'httpStatusCode':400, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'CORRELATION_CHECK_EMAIL': IdentifiableError['348bb8ae-575a-6fe9-4327-5811999def8f'], + 'CORRELATION_CHECK_WEBHOOK': IdentifiableError['b0c15051-de2d-29ef-260c-9585cddd701a'], + 'EMAIL_ADDRESS_NOT_SET': IdentifiableError['7cc1d85e-2f58-fc31-b644-3de8d0d3421f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-report___notification-recipient___update': { - 'CORRELATION_CHECK_EMAIL': {'message':'If "method" is email, "userId" must be set.', 'code':'CORRELATION_CHECK_EMAIL', 'id':'348bb8ae-575a-6fe9-4327-5811999def8f', 'httpStatusCode':400, [x: string]: any }, - 'CORRELATION_CHECK_WEBHOOK': {'message':'If "method" is webhook, "systemWebhookId" must be set.', 'code':'CORRELATION_CHECK_WEBHOOK', 'id':'b0c15051-de2d-29ef-260c-9585cddd701a', 'httpStatusCode':400, [x: string]: any }, - 'EMAIL_ADDRESS_NOT_SET': {'message':'Email address is not set.', 'code':'EMAIL_ADDRESS_NOT_SET', 'id':'7cc1d85e-2f58-fc31-b644-3de8d0d3421f', 'httpStatusCode':400, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'CORRELATION_CHECK_EMAIL': IdentifiableError['348bb8ae-575a-6fe9-4327-5811999def8f'], + 'CORRELATION_CHECK_WEBHOOK': IdentifiableError['b0c15051-de2d-29ef-260c-9585cddd701a'], + 'EMAIL_ADDRESS_NOT_SET': IdentifiableError['7cc1d85e-2f58-fc31-b644-3de8d0d3421f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___abuse-report___notification-recipient___delete': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___accounts___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___accounts___delete': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___accounts___find-by-email': { - 'USER_NOT_FOUND': {'message':'No such user who has the email address.', 'code':'USER_NOT_FOUND', 'id':'cb865949-8af5-4062-a88c-ef55e8786d1d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'USER_NOT_FOUND': IdentifiableError['cb865949-8af5-4062-a88c-ef55e8786d1d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___ad___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___ad___delete': { - 'NO_SUCH_AD': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'ccac9863-3a03-416e-b899-8a64041118b1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_AD': IdentifiableError['ccac9863-3a03-416e-b899-8a64041118b1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___ad___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___ad___update': { - 'NO_SUCH_AD': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'b7aa1727-1354-47bc-a182-3a9c3973d300', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_AD': IdentifiableError['b7aa1727-1354-47bc-a182-3a9c3973d300'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___announcements___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___announcements___delete': { - 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'ecad8040-a276-4e85-bda9-015a708d291e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANNOUNCEMENT': IdentifiableError['ecad8040-a276-4e85-bda9-015a708d291e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___announcements___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___announcements___update': { - 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'d3aae5a7-6372-4cb4-b61c-f511ffc2d7cc', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANNOUNCEMENT': IdentifiableError['d3aae5a7-6372-4cb4-b61c-f511ffc2d7cc'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___avatar-decorations___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___avatar-decorations___delete': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___avatar-decorations___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___avatar-decorations___update': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___delete-all-files-of-a-user': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___unset-user-avatar': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___unset-user-banner': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___drive___clean-remote-files': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___drive___cleanup': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___drive___files': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___drive___show-file': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'caf3ca38-c6e5-472e-a30c-b05377dcc240', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['caf3ca38-c6e5-472e-a30c-b05377dcc240'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___add-aliases-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___add': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'fc46b5a4-6b92-4c33-ac66-b806659bb5cf', [x: string]: any }, - 'DUPLICATE_NAME': {'message':'Duplicate name.', 'code':'DUPLICATE_NAME', 'id':'f7a3462c-4e6e-4069-8421-b9bd4f4c3975', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['fc46b5a4-6b92-4c33-ac66-b806659bb5cf'], + 'DUPLICATE_NAME': IdentifiableError['f7a3462c-4e6e-4069-8421-b9bd4f4c3975'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___copy': { - 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'e2785b66-dca3-4087-9cac-b93c541cc425', [x: string]: any }, - 'DUPLICATE_NAME': {'message':'Duplicate name.', 'code':'DUPLICATE_NAME', 'id':'f7a3462c-4e6e-4069-8421-b9bd4f4c3975', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_EMOJI': IdentifiableError['e2785b66-dca3-4087-9cac-b93c541cc425'], + 'DUPLICATE_NAME': IdentifiableError['f7a3462c-4e6e-4069-8421-b9bd4f4c3975'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___delete-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___delete': { - 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'be83669b-773a-44b7-b1f8-e5e5170ac3c2', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_EMOJI': IdentifiableError['be83669b-773a-44b7-b1f8-e5e5170ac3c2'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___import-zip': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___list-remote': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___remove-aliases-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___set-aliases-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___set-category-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___set-license-bulk': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___emoji___update': { - 'NO_SUCH_EMOJI': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'684dec9d-a8c2-4364-9aa8-456c49cb1dc8', [x: string]: any }, - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'14fb9fd9-0731-4e2f-aeb9-f09e4740333d', [x: string]: any }, - 'SAME_NAME_EMOJI_EXISTS': {'message':'Emoji that have same name already exists.', 'code':'SAME_NAME_EMOJI_EXISTS', 'id':'7180fe9d-1ee3-bff9-647d-fe9896d2ffb8', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_EMOJI': IdentifiableError['684dec9d-a8c2-4364-9aa8-456c49cb1dc8'], + 'NO_SUCH_FILE': IdentifiableError['14fb9fd9-0731-4e2f-aeb9-f09e4740333d'], + 'SAME_NAME_EMOJI_EXISTS': IdentifiableError['7180fe9d-1ee3-bff9-647d-fe9896d2ffb8'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___federation___delete-all-files': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___federation___refresh-remote-instance-metadata': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___federation___remove-all-following': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___federation___update-instance': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___get-index-stats': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___get-table-stats': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___get-user-ips': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___invite___create': { - 'INVALID_DATE_TIME': {'message':'Invalid date-time format', 'code':'INVALID_DATE_TIME', 'id':'f1380b15-3760-4c6c-a1db-5c3aaf1cbd49', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_DATE_TIME': IdentifiableError['f1380b15-3760-4c6c-a1db-5c3aaf1cbd49'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___invite___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___promo___create': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ee449fbe-af2a-453b-9cae-cf2fe7c895fc', [x: string]: any }, - 'ALREADY_PROMOTED': {'message':'The note has already promoted.', 'code':'ALREADY_PROMOTED', 'id':'ae427aa2-7a41-484f-a18c-2c1104051604', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['ee449fbe-af2a-453b-9cae-cf2fe7c895fc'], + 'ALREADY_PROMOTED': IdentifiableError['ae427aa2-7a41-484f-a18c-2c1104051604'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___queue___clear': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___queue___deliver-delayed': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___queue___inbox-delayed': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___queue___promote': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___queue___stats': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___relays___add': { - 'INVALID_URL': {'message':'Invalid URL', 'code':'INVALID_URL', 'id':'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_URL': IdentifiableError['fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___relays___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___relays___remove': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___reset-password': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___resolve-abuse-user-report': { - 'NO_SUCH_ABUSE_REPORT': {'message':'No such abuse report.', 'code':'NO_SUCH_ABUSE_REPORT', 'id':'ac3794dd-2ce4-d878-e546-73c60c06b398', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ABUSE_REPORT': IdentifiableError['ac3794dd-2ce4-d878-e546-73c60c06b398'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___send-email': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___server-info': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___show-moderation-logs': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___show-user': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___show-users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___suspend-user': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___unsuspend-user': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___update-meta': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___delete-account': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___update-user-note': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___delete': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de0d6ecd-8e0a-4253-88ff-74bc89ae3d45', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['de0d6ecd-8e0a-4253-88ff-74bc89ae3d45'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___show': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'07dc7d34-c0d8-49b7-96c6-db3ce64ee0b3', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['07dc7d34-c0d8-49b7-96c6-db3ce64ee0b3'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___update': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'cd23ef55-09ad-428a-ac61-95a45e124b32', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['cd23ef55-09ad-428a-ac61-95a45e124b32'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___assign': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6503c040-6af4-4ed9-bf07-f2dd16678eab', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'558ea170-f653-4700-94d0-5a818371d0df', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'25b5bc31-dc79-4ebd-9bd2-c84978fd052c', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['6503c040-6af4-4ed9-bf07-f2dd16678eab'], + 'NO_SUCH_USER': IdentifiableError['558ea170-f653-4700-94d0-5a818371d0df'], + 'ACCESS_DENIED': IdentifiableError['25b5bc31-dc79-4ebd-9bd2-c84978fd052c'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___unassign': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6e519036-a70d-4c76-b679-bc8fb18194e2', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'2b730f78-1179-461b-88ad-d24c9af1a5ce', [x: string]: any }, - 'NOT_ASSIGNED': {'message':'Not assigned.', 'code':'NOT_ASSIGNED', 'id':'b9060ac7-5c94-4da4-9f55-2047c953df44', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'24636eee-e8c1-493e-94b2-e16ad401e262', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['6e519036-a70d-4c76-b679-bc8fb18194e2'], + 'NO_SUCH_USER': IdentifiableError['2b730f78-1179-461b-88ad-d24c9af1a5ce'], + 'NOT_ASSIGNED': IdentifiableError['b9060ac7-5c94-4da4-9f55-2047c953df44'], + 'ACCESS_DENIED': IdentifiableError['24636eee-e8c1-493e-94b2-e16ad401e262'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___update-default-policies': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___roles___users': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'224eff5e-2488-4b18-b3e7-f50d94421648', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['224eff5e-2488-4b18-b3e7-f50d94421648'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___system-webhook___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___system-webhook___delete': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___system-webhook___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___system-webhook___show': { - 'NO_SUCH_SYSTEM_WEBHOOK': {'message':'No such SystemWebhook.', 'code':'NO_SUCH_SYSTEM_WEBHOOK', 'id':'38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_SYSTEM_WEBHOOK': IdentifiableError['38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'admin___system-webhook___update': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'announcements': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'announcements___show': { - 'NO_SUCH_ANNOUNCEMENT': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'b57b5e1d-4f49-404a-9edb-46b00268f121', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANNOUNCEMENT': IdentifiableError['b57b5e1d-4f49-404a-9edb-46b00268f121'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___create': { - 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'95063e93-a283-4b8b-9aa5-bcdb8df69a7f', [x: string]: any }, - 'TOO_MANY_ANTENNAS': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'faf47050-e8b5-438c-913c-db2b1576fde4', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER_LIST': IdentifiableError['95063e93-a283-4b8b-9aa5-bcdb8df69a7f'], + 'TOO_MANY_ANTENNAS': IdentifiableError['faf47050-e8b5-438c-913c-db2b1576fde4'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___delete': { - 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'b34dcf9d-348f-44bb-99d0-6c9314cfe2df', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANTENNA': IdentifiableError['b34dcf9d-348f-44bb-99d0-6c9314cfe2df'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___notes': { - 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'850926e0-fd3b-49b6-b69a-b28a5dbd82fe', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANTENNA': IdentifiableError['850926e0-fd3b-49b6-b69a-b28a5dbd82fe'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___show': { - 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'c06569fb-b025-4f23-b22d-1fcd20d2816b', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANTENNA': IdentifiableError['c06569fb-b025-4f23-b22d-1fcd20d2816b'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'antennas___update': { - 'NO_SUCH_ANTENNA': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'10c673ac-8852-48eb-aa1f-f5b67f069290', [x: string]: any }, - 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'1c6b35c9-943e-48c2-81e4-2844989407f7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ANTENNA': IdentifiableError['10c673ac-8852-48eb-aa1f-f5b67f069290'], + 'NO_SUCH_USER_LIST': IdentifiableError['1c6b35c9-943e-48c2-81e4-2844989407f7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'ap___get': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'ap___show': { - 'NO_SUCH_OBJECT': {'message':'No such object.', 'code':'NO_SUCH_OBJECT', 'id':'dc94d745-1262-4e63-a17d-fecaa57efc82', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_OBJECT': IdentifiableError['dc94d745-1262-4e63-a17d-fecaa57efc82'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'app___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'app___show': { - 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'dce83913-2dc6-4093-8a7b-71dbb11718a3', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_APP': IdentifiableError['dce83913-2dc6-4093-8a7b-71dbb11718a3'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'auth___accept': { - 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'9c72d8de-391a-43c1-9d06-08d29efde8df', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_SESSION': IdentifiableError['9c72d8de-391a-43c1-9d06-08d29efde8df'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'auth___session___generate': { - 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'92f93e63-428e-4f2f-a5a4-39e1407fe998', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_APP': IdentifiableError['92f93e63-428e-4f2f-a5a4-39e1407fe998'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'auth___session___show': { - 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'bd72c97d-eba7-4adb-a467-f171b8847250', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_SESSION': IdentifiableError['bd72c97d-eba7-4adb-a467-f171b8847250'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'auth___session___userkey': { - 'NO_SUCH_APP': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d', [x: string]: any }, - 'NO_SUCH_SESSION': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3', [x: string]: any }, - 'PENDING_SESSION': {'message':'This session is not completed yet.', 'code':'PENDING_SESSION', 'id':'8c8a4145-02cc-4cca-8e66-29ba60445a8e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_APP': IdentifiableError['fcab192a-2c5a-43b7-8ad8-9b7054d8d40d'], + 'NO_SUCH_SESSION': IdentifiableError['5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3'], + 'PENDING_SESSION': IdentifiableError['8c8a4145-02cc-4cca-8e66-29ba60445a8e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'blocking___create': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'7cc4f851-e2f1-4621-9633-ec9e1d00c01e', [x: string]: any }, - 'BLOCKEE_IS_YOURSELF': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'88b19138-f28d-42c0-8499-6a31bbd0fdc6', [x: string]: any }, - 'ALREADY_BLOCKING': {'message':'You are already blocking that user.', 'code':'ALREADY_BLOCKING', 'id':'787fed64-acb9-464a-82eb-afbd745b9614', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['7cc4f851-e2f1-4621-9633-ec9e1d00c01e'], + 'BLOCKEE_IS_YOURSELF': IdentifiableError['88b19138-f28d-42c0-8499-6a31bbd0fdc6'], + 'ALREADY_BLOCKING': IdentifiableError['787fed64-acb9-464a-82eb-afbd745b9614'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'blocking___delete': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'8621d8bf-c358-4303-a066-5ea78610eb3f', [x: string]: any }, - 'BLOCKEE_IS_YOURSELF': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'06f6fac6-524b-473c-a354-e97a40ae6eac', [x: string]: any }, - 'NOT_BLOCKING': {'message':'You are not blocking that user.', 'code':'NOT_BLOCKING', 'id':'291b2efa-60c6-45c0-9f6a-045c8f9b02cd', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['8621d8bf-c358-4303-a066-5ea78610eb3f'], + 'BLOCKEE_IS_YOURSELF': IdentifiableError['06f6fac6-524b-473c-a354-e97a40ae6eac'], + 'NOT_BLOCKING': IdentifiableError['291b2efa-60c6-45c0-9f6a-045c8f9b02cd'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'blocking___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___create': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___featured': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___follow': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'c0031718-d573-4e85-928e-10039f1fbb68', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['c0031718-d573-4e85-928e-10039f1fbb68'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___followed': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___owned': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___show': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'6f6c314b-7486-4897-8966-c04a66a02923', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['6f6c314b-7486-4897-8966-c04a66a02923'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___timeline': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___unfollow': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'19959ee9-0153-4c51-bbd9-a98c49dc59d6', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['19959ee9-0153-4c51-bbd9-a98c49dc59d6'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___update': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'f9c5467f-d492-4c3c-9a8d-a70dacc86512', [x: string]: any }, - 'ACCESS_DENIED': {'message':'You do not have edit privilege of the channel.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fdf-b8df-057788cce513', [x: string]: any }, - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e86c14a4-0da2-4032-8df3-e737a04c7f3b', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['f9c5467f-d492-4c3c-9a8d-a70dacc86512'], + 'ACCESS_DENIED': IdentifiableError['1fb7cb09-d46a-4fdf-b8df-057788cce513'], + 'NO_SUCH_FILE': IdentifiableError['e86c14a4-0da2-4032-8df3-e737a04c7f3b'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___favorite': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4938f5f3-6167-4c04-9149-6607b7542861', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['4938f5f3-6167-4c04-9149-6607b7542861'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___unfavorite': { - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'353c68dd-131a-476c-aa99-88a345e83668', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CHANNEL': IdentifiableError['353c68dd-131a-476c-aa99-88a345e83668'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___my-favorites': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'channels___search': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___active-users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___ap-request': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___drive': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___federation': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___instance': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___user___drive': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___user___following': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___user___notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___user___pv': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___user___reactions': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'charts___users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___add-note': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'d6e76cc0-a1b5-4c7c-a287-73fa9c716dcf', [x: string]: any }, - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b', [x: string]: any }, - 'ALREADY_CLIPPED': {'message':'The note has already been clipped.', 'code':'ALREADY_CLIPPED', 'id':'734806c4-542c-463a-9311-15c512803965', [x: string]: any }, - 'TOO_MANY_CLIP_NOTES': {'message':'You cannot add notes to the clip any more.', 'code':'TOO_MANY_CLIP_NOTES', 'id':'f0dba960-ff73-4615-8df4-d6ac5d9dc118', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['d6e76cc0-a1b5-4c7c-a287-73fa9c716dcf'], + 'NO_SUCH_NOTE': IdentifiableError['fc8c0b49-c7a3-4664-a0a6-b418d386bb8b'], + 'ALREADY_CLIPPED': IdentifiableError['734806c4-542c-463a-9311-15c512803965'], + 'TOO_MANY_CLIP_NOTES': IdentifiableError['f0dba960-ff73-4615-8df4-d6ac5d9dc118'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___remove-note': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b80525c6-97f7-49d7-a42d-ebccd49cfd52', [x: string]: any }, - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'aff017de-190e-434b-893e-33a9ff5049d8', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['b80525c6-97f7-49d7-a42d-ebccd49cfd52'], + 'NO_SUCH_NOTE': IdentifiableError['aff017de-190e-434b-893e-33a9ff5049d8'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___create': { - 'TOO_MANY_CLIPS': {'message':'You cannot create clip any more.', 'code':'TOO_MANY_CLIPS', 'id':'920f7c2d-6208-4b76-8082-e632020f5883', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'TOO_MANY_CLIPS': IdentifiableError['920f7c2d-6208-4b76-8082-e632020f5883'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___delete': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'70ca08ba-6865-4630-b6fb-8494759aa754', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['70ca08ba-6865-4630-b6fb-8494759aa754'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___notes': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'1d7645e6-2b6d-4635-b0fe-fe22b0e72e00', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['1d7645e6-2b6d-4635-b0fe-fe22b0e72e00'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___show': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'c3c5fe33-d62c-44d2-9ea5-d997703f5c20', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['c3c5fe33-d62c-44d2-9ea5-d997703f5c20'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___update': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b4d92d70-b216-46fa-9a3f-a8c811699257', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['b4d92d70-b216-46fa-9a3f-a8c811699257'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___favorite': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'4c2aaeae-80d8-4250-9606-26cb1fdb77a5', [x: string]: any }, - 'ALREADY_FAVORITED': {'message':'The clip has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'92658936-c625-4273-8326-2d790129256e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['4c2aaeae-80d8-4250-9606-26cb1fdb77a5'], + 'ALREADY_FAVORITED': IdentifiableError['92658936-c625-4273-8326-2d790129256e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___unfavorite': { - 'NO_SUCH_CLIP': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'2603966e-b865-426c-94a7-af4a01241dc1', [x: string]: any }, - 'NOT_FAVORITED': {'message':'You have not favorited the clip.', 'code':'NOT_FAVORITED', 'id':'90c3a9e8-b321-4dae-bf57-2bf79bbcc187', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_CLIP': IdentifiableError['2603966e-b865-426c-94a7-af4a01241dc1'], + 'NOT_FAVORITED': IdentifiableError['90c3a9e8-b321-4dae-bf57-2bf79bbcc187'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'clips___my-favorites': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___attached-notes': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'c118ece3-2e4b-4296-99d1-51756e32d232', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['c118ece3-2e4b-4296-99d1-51756e32d232'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___check-existence': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___create': { - 'INVALID_FILE_NAME': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'f449b209-0c60-4e51-84d5-29486263bfd4', [x: string]: any }, - 'INAPPROPRIATE': {'message':'Cannot upload the file because it has been determined that it possibly contains inappropriate content.', 'code':'INAPPROPRIATE', 'id':'bec5bd69-fba3-43c9-b4fb-2894b66ad5d2', [x: string]: any }, - 'NO_FREE_SPACE': {'message':'Cannot upload the file because you have no free space of drive.', 'code':'NO_FREE_SPACE', 'id':'d08dbc37-a6a9-463a-8c47-96c32ab5f064', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_FILE_NAME': IdentifiableError['f449b209-0c60-4e51-84d5-29486263bfd4'], + 'INAPPROPRIATE': IdentifiableError['bec5bd69-fba3-43c9-b4fb-2894b66ad5d2'], + 'NO_FREE_SPACE': IdentifiableError['d08dbc37-a6a9-463a-8c47-96c32ab5f064'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___delete': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'908939ec-e52b-4458-b395-1025195cea58', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'5eb8d909-2540-4970-90b8-dd6f86088121', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['908939ec-e52b-4458-b395-1025195cea58'], + 'ACCESS_DENIED': IdentifiableError['5eb8d909-2540-4970-90b8-dd6f86088121'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___find-by-hash': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___find': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___show': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'067bc436-2718-4795-b0fb-ecbe43949e31', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'25b73c73-68b1-41d0-bad1-381cfdf6579f', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['067bc436-2718-4795-b0fb-ecbe43949e31'], + 'ACCESS_DENIED': IdentifiableError['25b73c73-68b1-41d0-bad1-381cfdf6579f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___update': { - 'INVALID_FILE_NAME': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'395e7156-f9f0-475e-af89-53c3c23080c2', [x: string]: any }, - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e7778c7e-3af9-49cd-9690-6dbc3e6c972d', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'01a53b27-82fc-445b-a0c1-b558465a8ed2', [x: string]: any }, - 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'ea8fb7a5-af77-4a08-b608-c0218176cd73', [x: string]: any }, - 'RESTRICTED_BY_ROLE': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'7f59dccb-f465-75ab-5cf4-3ce44e3282f7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_FILE_NAME': IdentifiableError['395e7156-f9f0-475e-af89-53c3c23080c2'], + 'NO_SUCH_FILE': IdentifiableError['e7778c7e-3af9-49cd-9690-6dbc3e6c972d'], + 'ACCESS_DENIED': IdentifiableError['01a53b27-82fc-445b-a0c1-b558465a8ed2'], + 'NO_SUCH_FOLDER': IdentifiableError['ea8fb7a5-af77-4a08-b608-c0218176cd73'], + 'RESTRICTED_BY_ROLE': IdentifiableError['7f59dccb-f465-75ab-5cf4-3ce44e3282f7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___files___upload-from-url': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders___create': { - 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'53326628-a00d-40a6-a3cd-8975105c0f95', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FOLDER': IdentifiableError['53326628-a00d-40a6-a3cd-8975105c0f95'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders___delete': { - 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'1069098f-c281-440f-b085-f9932edbe091', [x: string]: any }, - 'HAS_CHILD_FILES_OR_FOLDERS': {'message':'This folder has child files or folders.', 'code':'HAS_CHILD_FILES_OR_FOLDERS', 'id':'b0fc8a17-963c-405d-bfbc-859a487295e1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FOLDER': IdentifiableError['1069098f-c281-440f-b085-f9932edbe091'], + 'HAS_CHILD_FILES_OR_FOLDERS': IdentifiableError['b0fc8a17-963c-405d-bfbc-859a487295e1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders___find': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders___show': { - 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'d74ab9eb-bb09-4bba-bf24-fb58f761e1e9', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FOLDER': IdentifiableError['d74ab9eb-bb09-4bba-bf24-fb58f761e1e9'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___folders___update': { - 'NO_SUCH_FOLDER': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'f7974dac-2c0d-4a27-926e-23583b28e98e', [x: string]: any }, - 'NO_SUCH_PARENT_FOLDER': {'message':'No such parent folder.', 'code':'NO_SUCH_PARENT_FOLDER', 'id':'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1', [x: string]: any }, - 'RECURSIVE_NESTING': {'message':'It can not be structured like nesting folders recursively.', 'code':'RECURSIVE_NESTING', 'id':'dbeb024837894013aed44279f9199740', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FOLDER': IdentifiableError['f7974dac-2c0d-4a27-926e-23583b28e98e'], + 'NO_SUCH_PARENT_FOLDER': IdentifiableError['ce104e3a-faaf-49d5-b459-10ff0cbbcaa1'], + 'RECURSIVE_NESTING': IdentifiableError['dbeb024837894013aed44279f9199740'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'drive___stream': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'email-address___available': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'endpoint': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'endpoints': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'export-custom-emojis': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___followers': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___following': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___instances': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___show-instance': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___update-remote-user': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'federation___stats': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___create': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, - 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'26fbe7bb-a331-4857-af17-205b426669a9', [x: string]: any }, - 'ALREADY_FOLLOWING': {'message':'You are already following that user.', 'code':'ALREADY_FOLLOWING', 'id':'35387507-38c7-4cb9-9197-300b93783fa0', [x: string]: any }, - 'BLOCKING': {'message':'You are blocking that user.', 'code':'BLOCKING', 'id':'4e2206ec-aa4f-4960-b865-6c23ac38e2d9', [x: string]: any }, - 'BLOCKED': {'message':'You are blocked by that user.', 'code':'BLOCKED', 'id':'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['fcd2eef9-a9b2-4c4f-8624-038099e90aa5'], + 'FOLLOWEE_IS_YOURSELF': IdentifiableError['26fbe7bb-a331-4857-af17-205b426669a9'], + 'ALREADY_FOLLOWING': IdentifiableError['35387507-38c7-4cb9-9197-300b93783fa0'], + 'BLOCKING': IdentifiableError['4e2206ec-aa4f-4960-b865-6c23ac38e2d9'], + 'BLOCKED': IdentifiableError['c4ab57cc-4e41-45e9-bfd9-584f61e35ce0'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___delete': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5b12c78d-2b28-4dca-99d2-f56139b42ff8', [x: string]: any }, - 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'d9e400b9-36b0-4808-b1d8-79e707f1296c', [x: string]: any }, - 'NOT_FOLLOWING': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['5b12c78d-2b28-4dca-99d2-f56139b42ff8'], + 'FOLLOWEE_IS_YOURSELF': IdentifiableError['d9e400b9-36b0-4808-b1d8-79e707f1296c'], + 'NOT_FOLLOWING': IdentifiableError['5dbf82f5-c92b-40b1-87d1-6c8c0741fd09'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___update': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'14318698-f67e-492a-99da-5353a5ac52be', [x: string]: any }, - 'FOLLOWEE_IS_YOURSELF': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'4c4cbaf9-962a-463b-8418-a5e365dbf2eb', [x: string]: any }, - 'NOT_FOLLOWING': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['14318698-f67e-492a-99da-5353a5ac52be'], + 'FOLLOWEE_IS_YOURSELF': IdentifiableError['4c4cbaf9-962a-463b-8418-a5e365dbf2eb'], + 'NOT_FOLLOWING': IdentifiableError['b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___update-all': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___invalidate': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b77e6ae6-a3e5-40da-9cc8-c240115479cc', [x: string]: any }, - 'FOLLOWER_IS_YOURSELF': {'message':'Follower is yourself.', 'code':'FOLLOWER_IS_YOURSELF', 'id':'07dc03b9-03da-422d-885b-438313707662', [x: string]: any }, - 'NOT_FOLLOWING': {'message':'The other use is not following you.', 'code':'NOT_FOLLOWING', 'id':'918faac3-074f-41ae-9c43-ed5d2946770d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['b77e6ae6-a3e5-40da-9cc8-c240115479cc'], + 'FOLLOWER_IS_YOURSELF': IdentifiableError['07dc03b9-03da-422d-885b-438313707662'], + 'NOT_FOLLOWING': IdentifiableError['918faac3-074f-41ae-9c43-ed5d2946770d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___requests___accept': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'66ce1645-d66c-46bb-8b79-96739af885bd', [x: string]: any }, - 'NO_FOLLOW_REQUEST': {'message':'No follow request.', 'code':'NO_FOLLOW_REQUEST', 'id':'bcde4f8b-0913-4614-8881-614e522fb041', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['66ce1645-d66c-46bb-8b79-96739af885bd'], + 'NO_FOLLOW_REQUEST': IdentifiableError['bcde4f8b-0913-4614-8881-614e522fb041'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___requests___cancel': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4e68c551-fc4c-4e46-bb41-7d4a37bf9dab', [x: string]: any }, - 'FOLLOW_REQUEST_NOT_FOUND': {'message':'Follow request not found.', 'code':'FOLLOW_REQUEST_NOT_FOUND', 'id':'089b125b-d338-482a-9a09-e2622ac9f8d4', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['4e68c551-fc4c-4e46-bb41-7d4a37bf9dab'], + 'FOLLOW_REQUEST_NOT_FOUND': IdentifiableError['089b125b-d338-482a-9a09-e2622ac9f8d4'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___requests___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'following___requests___reject': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'abc2ffa6-25b2-4380-ba99-321ff3a94555', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['abc2ffa6-25b2-4380-ba99-321ff3a94555'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___featured': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___popular': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___delete': { - 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'ae52f367-4bd7-4ecd-afc6-5672fff427f5', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_POST': IdentifiableError['ae52f367-4bd7-4ecd-afc6-5672fff427f5'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___like': { - 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'56c06af3-1287-442f-9701-c93f7c4a62ff', [x: string]: any }, - 'YOUR_POST': {'message':'You cannot like your post.', 'code':'YOUR_POST', 'id':'f78f1511-5ebc-4478-a888-1198d752da68', [x: string]: any }, - 'ALREADY_LIKED': {'message':'The post has already been liked.', 'code':'ALREADY_LIKED', 'id':'40e9ed56-a59c-473a-bf3f-f289c54fb5a7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_POST': IdentifiableError['56c06af3-1287-442f-9701-c93f7c4a62ff'], + 'YOUR_POST': IdentifiableError['f78f1511-5ebc-4478-a888-1198d752da68'], + 'ALREADY_LIKED': IdentifiableError['40e9ed56-a59c-473a-bf3f-f289c54fb5a7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___show': { - 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'1137bf14-c5b0-4604-85bb-5b5371b1cd45', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_POST': IdentifiableError['1137bf14-c5b0-4604-85bb-5b5371b1cd45'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___unlike': { - 'NO_SUCH_POST': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'c32e6dd0-b555-4413-925e-b3757d19ed84', [x: string]: any }, - 'NOT_LIKED': {'message':'You have not liked that post.', 'code':'NOT_LIKED', 'id':'e3e8e06e-be37-41f7-a5b4-87a8250288f0', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_POST': IdentifiableError['c32e6dd0-b555-4413-925e-b3757d19ed84'], + 'NOT_LIKED': IdentifiableError['e3e8e06e-be37-41f7-a5b4-87a8250288f0'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'gallery___posts___update': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'get-online-users-count': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'get-avatar-decorations': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'hashtags___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'hashtags___search': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'hashtags___show': { - 'NO_SUCH_HASHTAG': {'message':'No such hashtag.', 'code':'NO_SUCH_HASHTAG', 'id':'110ee688-193e-4a3a-9ecf-c167b2e6981e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_HASHTAG': IdentifiableError['110ee688-193e-4a3a-9ecf-c167b2e6981e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'hashtags___trend': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'hashtags___users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i': { - 'USER_IS_DELETED': {'message':'User is deleted.', 'code':'USER_IS_DELETED', 'id':'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a', 'kind':'permission', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'USER_IS_DELETED': IdentifiableError['e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___done': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___key-done': { - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'0d7ec6d2-e652-443e-a7bf-9ee9a0cd77b0', [x: string]: any }, - 'TWO_FACTOR_NOT_ENABLED': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'798d6847-b1ed-4f9c-b1f9-163c42655995', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INCORRECT_PASSWORD': IdentifiableError['0d7ec6d2-e652-443e-a7bf-9ee9a0cd77b0'], + 'TWO_FACTOR_NOT_ENABLED': IdentifiableError['798d6847-b1ed-4f9c-b1f9-163c42655995'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___password-less': { - 'NO_SECURITY_KEY': {'message':'No security key.', 'code':'NO_SECURITY_KEY', 'id':'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SECURITY_KEY': IdentifiableError['f9c54d7f-d4c2-4d3c-9a8g-a70daac86512'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___register-key': { - 'USER_NOT_FOUND': {'message':'User not found.', 'code':'USER_NOT_FOUND', 'id':'652f899f-66d4-490e-993e-6606c8ec04c3', [x: string]: any }, - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'38769596-efe2-4faf-9bec-abbb3f2cd9ba', [x: string]: any }, - 'TWO_FACTOR_NOT_ENABLED': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'bf32b864-449b-47b8-974e-f9a5468546f1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'USER_NOT_FOUND': IdentifiableError['652f899f-66d4-490e-993e-6606c8ec04c3'], + 'INCORRECT_PASSWORD': IdentifiableError['38769596-efe2-4faf-9bec-abbb3f2cd9ba'], + 'TWO_FACTOR_NOT_ENABLED': IdentifiableError['bf32b864-449b-47b8-974e-f9a5468546f1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___register': { - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'78d6c839-20c9-4c66-b90a-fc0542168b48', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INCORRECT_PASSWORD': IdentifiableError['78d6c839-20c9-4c66-b90a-fc0542168b48'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___update-key': { - 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'f9c5467f-d492-4d3c-9a8g-a70dacc86512', [x: string]: any }, - 'ACCESS_DENIED': {'message':'You do not have edit privilege of this key.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fff-b8df-057708cce513', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_KEY': IdentifiableError['f9c5467f-d492-4d3c-9a8g-a70dacc86512'], + 'ACCESS_DENIED': IdentifiableError['1fb7cb09-d46a-4fff-b8df-057708cce513'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___remove-key': { - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'141c598d-a825-44c8-9173-cfb9d92be493', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INCORRECT_PASSWORD': IdentifiableError['141c598d-a825-44c8-9173-cfb9d92be493'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___2fa___unregister': { - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'7add0395-9901-4098-82f9-4f67af65f775', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INCORRECT_PASSWORD': IdentifiableError['7add0395-9901-4098-82f9-4f67af65f775'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___apps': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___authorized-apps': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___claim-achievement': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___change-password': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___delete-account': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-blocking': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-following': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-mute': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-clips': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-favorites': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-user-lists': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___export-antennas': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___favorites': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___gallery___likes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___gallery___posts': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___import-blocking': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e', [x: string]: any }, - 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe', [x: string]: any }, - 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf', [x: string]: any }, - 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'6f3a4dcc-f060-a707-4950-806fbdbe60d6', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['ebb53e5f-6574-9c0c-0b92-7ca6def56d7e'], + 'UNEXPECTED_FILE_TYPE': IdentifiableError['b6fab7d6-d945-d67c-dfdb-32da1cd12cfe'], + 'TOO_BIG_FILE': IdentifiableError['b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf'], + 'EMPTY_FILE': IdentifiableError['6f3a4dcc-f060-a707-4950-806fbdbe60d6'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___import-following': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b98644cf-a5ac-4277-a502-0b8054a709a3', [x: string]: any }, - 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'660f3599-bce0-4f95-9dde-311fd841c183', [x: string]: any }, - 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'dee9d4ed-ad07-43ed-8b34-b2856398bc60', [x: string]: any }, - 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'31a1b42c-06f7-42ae-8a38-a661c5c9f691', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['b98644cf-a5ac-4277-a502-0b8054a709a3'], + 'UNEXPECTED_FILE_TYPE': IdentifiableError['660f3599-bce0-4f95-9dde-311fd841c183'], + 'TOO_BIG_FILE': IdentifiableError['dee9d4ed-ad07-43ed-8b34-b2856398bc60'], + 'EMPTY_FILE': IdentifiableError['31a1b42c-06f7-42ae-8a38-a661c5c9f691'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___import-muting': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e674141e-bd2a-ba85-e616-aefb187c9c2a', [x: string]: any }, - 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'568c6e42-c86c-ba09-c004-517f83f9f1a8', [x: string]: any }, - 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'9b4ada6d-d7f7-0472-0713-4f558bd1ec9c', [x: string]: any }, - 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'d2f12af1-e7b4-feac-86a3-519548f2728e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['e674141e-bd2a-ba85-e616-aefb187c9c2a'], + 'UNEXPECTED_FILE_TYPE': IdentifiableError['568c6e42-c86c-ba09-c004-517f83f9f1a8'], + 'TOO_BIG_FILE': IdentifiableError['9b4ada6d-d7f7-0472-0713-4f558bd1ec9c'], + 'EMPTY_FILE': IdentifiableError['d2f12af1-e7b4-feac-86a3-519548f2728e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___import-user-lists': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ea9cc34f-c415-4bc6-a6fe-28ac40357049', [x: string]: any }, - 'UNEXPECTED_FILE_TYPE': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'a3c9edda-dd9b-4596-be6a-150ef813745c', [x: string]: any }, - 'TOO_BIG_FILE': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9', [x: string]: any }, - 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'99efe367-ce6e-4d44-93f8-5fae7b040356', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['ea9cc34f-c415-4bc6-a6fe-28ac40357049'], + 'UNEXPECTED_FILE_TYPE': IdentifiableError['a3c9edda-dd9b-4596-be6a-150ef813745c'], + 'TOO_BIG_FILE': IdentifiableError['ae6e7a22-971b-4b52-b2be-fc0b9b121fe9'], + 'EMPTY_FILE': IdentifiableError['99efe367-ce6e-4d44-93f8-5fae7b040356'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___import-antennas': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'3b71d086-c3fa-431c-b01d-ded65a777172', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e842c379-8ac7-4cf7-b07a-4d4de7e4671c', [x: string]: any }, - 'EMPTY_FILE': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'7f60115d-8d93-4b0f-bd0e-3815dcbb389f', [x: string]: any }, - 'TOO_MANY_ANTENNAS': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'600917d4-a4cb-4cc5-8ba8-7ac8ea3c7779', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['3b71d086-c3fa-431c-b01d-ded65a777172'], + 'NO_SUCH_USER': IdentifiableError['e842c379-8ac7-4cf7-b07a-4d4de7e4671c'], + 'EMPTY_FILE': IdentifiableError['7f60115d-8d93-4b0f-bd0e-3815dcbb389f'], + 'TOO_MANY_ANTENNAS': IdentifiableError['600917d4-a4cb-4cc5-8ba8-7ac8ea3c7779'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___notifications': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___notifications-grouped': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___page-likes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___pages': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___pin': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'56734f8b-3928-431e-bf80-6ff87df40cb3', [x: string]: any }, - 'PIN_LIMIT_EXCEEDED': {'message':'You can not pin notes any more.', 'code':'PIN_LIMIT_EXCEEDED', 'id':'72dab508-c64d-498f-8740-a8eec1ba385a', [x: string]: any }, - 'ALREADY_PINNED': {'message':'That note has already been pinned.', 'code':'ALREADY_PINNED', 'id':'8b18c2b7-68fe-4edb-9892-c0cbaeb6c913', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['56734f8b-3928-431e-bf80-6ff87df40cb3'], + 'PIN_LIMIT_EXCEEDED': IdentifiableError['72dab508-c64d-498f-8740-a8eec1ba385a'], + 'ALREADY_PINNED': IdentifiableError['8b18c2b7-68fe-4edb-9892-c0cbaeb6c913'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___read-all-unread-notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___read-announcement': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___regenerate-token': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___get-all': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___get-detail': { - 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'97a1e8e7-c0f7-47d2-957a-92e61256e01a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_KEY': IdentifiableError['97a1e8e7-c0f7-47d2-957a-92e61256e01a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___get': { - 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_KEY': IdentifiableError['ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___keys-with-type': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___keys': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___remove': { - 'NO_SUCH_KEY': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_KEY': IdentifiableError['1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___scopes-with-domain': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___registry___set': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___revoke-token': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___signin-history': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___unpin': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'454170ce-9d63-4a43-9da1-ea10afe81e21', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['454170ce-9d63-4a43-9da1-ea10afe81e21'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___update-email': { - 'INCORRECT_PASSWORD': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3', [x: string]: any }, - 'UNAVAILABLE': {'message':'Unavailable email address.', 'code':'UNAVAILABLE', 'id':'a2defefb-f220-8849-0af6-17f816099323', [x: string]: any }, - 'EMAIL_REQUIRED': {'message':'Email address is required.', 'code':'EMAIL_REQUIRED', 'id':'324c7a88-59f2-492f-903f-89134f93e47e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INCORRECT_PASSWORD': IdentifiableError['e54c1d7e-e7d6-4103-86b6-0a95069b4ad3'], + 'UNAVAILABLE': IdentifiableError['a2defefb-f220-8849-0af6-17f816099323'], + 'EMAIL_REQUIRED': IdentifiableError['324c7a88-59f2-492f-903f-89134f93e47e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___update': { - 'NO_SUCH_AVATAR': {'message':'No such avatar file.', 'code':'NO_SUCH_AVATAR', 'id':'539f3a45-f215-4f81-a9a8-31293640207f', [x: string]: any }, - 'NO_SUCH_BANNER': {'message':'No such banner file.', 'code':'NO_SUCH_BANNER', 'id':'0d8f5629-f210-41c2-9433-735831a58595', [x: string]: any }, - 'AVATAR_NOT_AN_IMAGE': {'message':'The file specified as an avatar is not an image.', 'code':'AVATAR_NOT_AN_IMAGE', 'id':'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191', [x: string]: any }, - 'BANNER_NOT_AN_IMAGE': {'message':'The file specified as a banner is not an image.', 'code':'BANNER_NOT_AN_IMAGE', 'id':'75aedb19-2afd-4e6d-87fc-67941256fa60', [x: string]: any }, - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'8e01b590-7eb9-431b-a239-860e086c408e', [x: string]: any }, - 'INVALID_REGEXP': {'message':'Invalid Regular Expression.', 'code':'INVALID_REGEXP', 'id':'0d786918-10df-41cd-8f33-8dec7d9a89a5', [x: string]: any }, - 'TOO_MANY_MUTED_WORDS': {'message':'Too many muted words.', 'code':'TOO_MANY_MUTED_WORDS', 'id':'010665b1-a211-42d2-bc64-8f6609d79785', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, - 'URI_NULL': {'message':'User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'bf326f31-d430-4f97-9933-5d61e4d48a23', [x: string]: any }, - 'FORBIDDEN_TO_SET_YOURSELF': {'message':'You can\'t set yourself as your own alias.', 'code':'FORBIDDEN_TO_SET_YOURSELF', 'id':'25c90186-4ab0-49c8-9bba-a1fa6c202ba4', [x: string]: any }, - 'RESTRICTED_BY_ROLE': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'8feff0ba-5ab5-585b-31f4-4df816663fad', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_AVATAR': IdentifiableError['539f3a45-f215-4f81-a9a8-31293640207f'], + 'NO_SUCH_BANNER': IdentifiableError['0d8f5629-f210-41c2-9433-735831a58595'], + 'AVATAR_NOT_AN_IMAGE': IdentifiableError['f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191'], + 'BANNER_NOT_AN_IMAGE': IdentifiableError['75aedb19-2afd-4e6d-87fc-67941256fa60'], + 'NO_SUCH_PAGE': IdentifiableError['8e01b590-7eb9-431b-a239-860e086c408e'], + 'INVALID_REGEXP': IdentifiableError['0d786918-10df-41cd-8f33-8dec7d9a89a5'], + 'TOO_MANY_MUTED_WORDS': IdentifiableError['010665b1-a211-42d2-bc64-8f6609d79785'], + 'NO_SUCH_USER': IdentifiableError['fcd2eef9-a9b2-4c4f-8624-038099e90aa5'], + 'URI_NULL': IdentifiableError['bf326f31-d430-4f97-9933-5d61e4d48a23'], + 'FORBIDDEN_TO_SET_YOURSELF': IdentifiableError['25c90186-4ab0-49c8-9bba-a1fa6c202ba4'], + 'RESTRICTED_BY_ROLE': IdentifiableError['8feff0ba-5ab5-585b-31f4-4df816663fad'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___move': { - 'DESTINATION_ACCOUNT_FORBIDS': {'message':'Destination account doesn\'t have proper \'Known As\' alias, or has already moved.', 'code':'DESTINATION_ACCOUNT_FORBIDS', 'id':'b5c90186-4ab0-49c8-9bba-a1f766282ba4', [x: string]: any }, - 'NOT_ROOT_FORBIDDEN': {'message':'The root can\'t migrate.', 'code':'NOT_ROOT_FORBIDDEN', 'id':'4362e8dc-731f-4ad8-a694-be2a88922a24', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, - 'URI_NULL': {'message':'Local User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'95ba11b9-90e8-43a5-ba16-7acc1ab32e71', [x: string]: any }, - 'ALREADY_MOVED': {'message':'Account was already moved to another account.', 'code':'ALREADY_MOVED', 'id':'b234a14e-9ebe-4581-8000-074b3c215962', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'DESTINATION_ACCOUNT_FORBIDS': IdentifiableError['b5c90186-4ab0-49c8-9bba-a1f766282ba4'], + 'NOT_ROOT_FORBIDDEN': IdentifiableError['4362e8dc-731f-4ad8-a694-be2a88922a24'], + 'NO_SUCH_USER': IdentifiableError['fcd2eef9-a9b2-4c4f-8624-038099e90aa5'], + 'URI_NULL': IdentifiableError['95ba11b9-90e8-43a5-ba16-7acc1ab32e71'], + 'ALREADY_MOVED': IdentifiableError['b234a14e-9ebe-4581-8000-074b3c215962'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___webhooks___create': { - 'TOO_MANY_WEBHOOKS': {'message':'You cannot create webhook any more.', 'code':'TOO_MANY_WEBHOOKS', 'id':'87a9bb19-111e-4e37-81d3-a3e7426453b0', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'TOO_MANY_WEBHOOKS': IdentifiableError['87a9bb19-111e-4e37-81d3-a3e7426453b0'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___webhooks___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___webhooks___show': { - 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'50f614d9-3047-4f7e-90d8-ad6b2d5fb098', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_WEBHOOK': IdentifiableError['50f614d9-3047-4f7e-90d8-ad6b2d5fb098'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___webhooks___update': { - 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'fb0fea69-da18-45b1-828d-bd4fd1612518', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_WEBHOOK': IdentifiableError['fb0fea69-da18-45b1-828d-bd4fd1612518'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'i___webhooks___delete': { - 'NO_SUCH_WEBHOOK': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'bae73e5a-5522-4965-ae19-3a8688e71d82', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_WEBHOOK': IdentifiableError['bae73e5a-5522-4965-ae19-3a8688e71d82'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'invite___create': { - 'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE': {'message':'You have exceeded the limit for creating an invitation code.', 'code':'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE', 'id':'8b165dd3-6f37-4557-8db1-73175d63c641', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE': IdentifiableError['8b165dd3-6f37-4557-8db1-73175d63c641'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'invite___delete': { - 'NO_SUCH_INVITE_CODE': {'message':'No such invite code.', 'code':'NO_SUCH_INVITE_CODE', 'id':'cd4f9ae4-7854-4e3e-8df9-c296f051e634', [x: string]: any }, - 'CAN_NOT_DELETE_INVITE_CODE': {'message':'You can\'t delete this invite code.', 'code':'CAN_NOT_DELETE_INVITE_CODE', 'id':'ff17af39-000c-4d4e-abdf-848fa30fc1ce', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'5eb8d909-2540-4970-90b8-dd6f86088121', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_INVITE_CODE': IdentifiableError['cd4f9ae4-7854-4e3e-8df9-c296f051e634'], + 'CAN_NOT_DELETE_INVITE_CODE': IdentifiableError['ff17af39-000c-4d4e-abdf-848fa30fc1ce'], + 'ACCESS_DENIED': IdentifiableError['5eb8d909-2540-4970-90b8-dd6f86088121'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'invite___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'invite___limit': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'meta': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'emojis': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'emoji': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'miauth___gen-token': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'mute___create': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'6fef56f3-e765-4957-88e5-c6f65329b8a5', [x: string]: any }, - 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'a4619cb2-5f23-484b-9301-94c903074e10', [x: string]: any }, - 'ALREADY_MUTING': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'7e7359cb-160c-4956-b08f-4d1c653cd007', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['6fef56f3-e765-4957-88e5-c6f65329b8a5'], + 'MUTEE_IS_YOURSELF': IdentifiableError['a4619cb2-5f23-484b-9301-94c903074e10'], + 'ALREADY_MUTING': IdentifiableError['7e7359cb-160c-4956-b08f-4d1c653cd007'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'mute___delete': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b851d00b-8ab1-4a56-8b1b-e24187cb48ef', [x: string]: any }, - 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9', [x: string]: any }, - 'NOT_MUTING': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'5467d020-daa9-4553-81e1-135c0c35a96d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['b851d00b-8ab1-4a56-8b1b-e24187cb48ef'], + 'MUTEE_IS_YOURSELF': IdentifiableError['f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9'], + 'NOT_MUTING': IdentifiableError['5467d020-daa9-4553-81e1-135c0c35a96d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'mute___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'renote-mute___create': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5e0a5dff-1e94-4202-87ae-4d9c89eb2271', [x: string]: any }, - 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'37285718-52f7-4aef-b7de-c38b8e8a8420', [x: string]: any }, - 'ALREADY_MUTING': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'ccfecbe4-1f1c-4fc2-8a3d-c3ffee61cb7b', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['5e0a5dff-1e94-4202-87ae-4d9c89eb2271'], + 'MUTEE_IS_YOURSELF': IdentifiableError['37285718-52f7-4aef-b7de-c38b8e8a8420'], + 'ALREADY_MUTING': IdentifiableError['ccfecbe4-1f1c-4fc2-8a3d-c3ffee61cb7b'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'renote-mute___delete': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'9b6728cf-638c-4aa1-bedb-e07d8101474d', [x: string]: any }, - 'MUTEE_IS_YOURSELF': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'619b1314-0850-4597-a242-e245f3da42af', [x: string]: any }, - 'NOT_MUTING': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'2e4ef874-8bf0-4b4b-b069-4598f6d05817', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['9b6728cf-638c-4aa1-bedb-e07d8101474d'], + 'MUTEE_IS_YOURSELF': IdentifiableError['619b1314-0850-4597-a242-e245f3da42af'], + 'NOT_MUTING': IdentifiableError['2e4ef874-8bf0-4b4b-b069-4598f6d05817'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'renote-mute___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'my___apps': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___children': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___clips': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'47db1a1c-b0af-458d-8fb4-986e4efafe1e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['47db1a1c-b0af-458d-8fb4-986e4efafe1e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___conversation': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'e1035875-9551-45ec-afa8-1ded1fcb53c8', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['e1035875-9551-45ec-afa8-1ded1fcb53c8'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___create': { - 'NO_SUCH_RENOTE_TARGET': {'message':'No such renote target.', 'code':'NO_SUCH_RENOTE_TARGET', 'id':'b5c90186-4ab0-49c8-9bba-a1f76c282ba4', [x: string]: any }, - 'CANNOT_RENOTE_TO_A_PURE_RENOTE': {'message':'You can not Renote a pure Renote.', 'code':'CANNOT_RENOTE_TO_A_PURE_RENOTE', 'id':'fd4cc33e-2a37-48dd-99cc-9b806eb2031a', [x: string]: any }, - 'CANNOT_RENOTE_DUE_TO_VISIBILITY': {'message':'You can not Renote due to target visibility.', 'code':'CANNOT_RENOTE_DUE_TO_VISIBILITY', 'id':'be9529e9-fe72-4de0-ae43-0b363c4938af', [x: string]: any }, - 'NO_SUCH_REPLY_TARGET': {'message':'No such reply target.', 'code':'NO_SUCH_REPLY_TARGET', 'id':'749ee0f6-d3da-459a-bf02-282e2da4292c', [x: string]: any }, - 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE': {'message':'You cannot reply to an invisible Note.', 'code':'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE', 'id':'b98980fa-3780-406c-a935-b6d0eeee10d1', [x: string]: any }, - 'CANNOT_REPLY_TO_A_PURE_RENOTE': {'message':'You can not reply to a pure Renote.', 'code':'CANNOT_REPLY_TO_A_PURE_RENOTE', 'id':'3ac74a84-8fd5-4bb0-870f-01804f82ce15', [x: string]: any }, - 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY': {'message':'You cannot reply to a specified visibility note with extended visibility.', 'code':'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY', 'id':'ed940410-535c-4d5e-bfa3-af798671e93c', [x: string]: any }, - 'CANNOT_CREATE_ALREADY_EXPIRED_POLL': {'message':'Poll is already expired.', 'code':'CANNOT_CREATE_ALREADY_EXPIRED_POLL', 'id':'04da457d-b083-4055-9082-955525eda5a5', [x: string]: any }, - 'NO_SUCH_CHANNEL': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'b1653923-5453-4edc-b786-7c4f39bb0bbb', [x: string]: any }, - 'YOU_HAVE_BEEN_BLOCKED': {'message':'You have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'b390d7e1-8a5e-46ed-b625-06271cafd3d3', [x: string]: any }, - 'NO_SUCH_FILE': {'message':'Some files are not found.', 'code':'NO_SUCH_FILE', 'id':'b6992544-63e7-67f0-fa7f-32444b1b5306', [x: string]: any }, - 'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL': {'message':'Cannot renote outside of channel.', 'code':'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL', 'id':'33510210-8452-094c-6227-4a6c05d99f00', [x: string]: any }, - 'CONTAINS_PROHIBITED_WORDS': {'message':'Cannot post because it contains prohibited words.', 'code':'CONTAINS_PROHIBITED_WORDS', 'id':'aa6e01d3-a85c-669d-758a-76aab43af334', [x: string]: any }, - 'CONTAINS_TOO_MANY_MENTIONS': {'message':'Cannot post because it exceeds the allowed number of mentions.', 'code':'CONTAINS_TOO_MANY_MENTIONS', 'id':'4de0363a-3046-481b-9b0f-feff3e211025', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_RENOTE_TARGET': IdentifiableError['b5c90186-4ab0-49c8-9bba-a1f76c282ba4'], + 'CANNOT_RENOTE_TO_A_PURE_RENOTE': IdentifiableError['fd4cc33e-2a37-48dd-99cc-9b806eb2031a'], + 'CANNOT_RENOTE_DUE_TO_VISIBILITY': IdentifiableError['be9529e9-fe72-4de0-ae43-0b363c4938af'], + 'NO_SUCH_REPLY_TARGET': IdentifiableError['749ee0f6-d3da-459a-bf02-282e2da4292c'], + 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE': IdentifiableError['b98980fa-3780-406c-a935-b6d0eeee10d1'], + 'CANNOT_REPLY_TO_A_PURE_RENOTE': IdentifiableError['3ac74a84-8fd5-4bb0-870f-01804f82ce15'], + 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY': IdentifiableError['ed940410-535c-4d5e-bfa3-af798671e93c'], + 'CANNOT_CREATE_ALREADY_EXPIRED_POLL': IdentifiableError['04da457d-b083-4055-9082-955525eda5a5'], + 'NO_SUCH_CHANNEL': IdentifiableError['b1653923-5453-4edc-b786-7c4f39bb0bbb'], + 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['b390d7e1-8a5e-46ed-b625-06271cafd3d3'], + 'NO_SUCH_FILE': IdentifiableError['b6992544-63e7-67f0-fa7f-32444b1b5306'], + 'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL': IdentifiableError['33510210-8452-094c-6227-4a6c05d99f00'], + 'CONTAINS_PROHIBITED_WORDS': IdentifiableError['aa6e01d3-a85c-669d-758a-76aab43af334'], + 'CONTAINS_TOO_MANY_MENTIONS': IdentifiableError['4de0363a-3046-481b-9b0f-feff3e211025'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___delete': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'490be23f-8c1f-4796-819f-94cb4f9d1630', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['490be23f-8c1f-4796-819f-94cb4f9d1630'], + 'ACCESS_DENIED': IdentifiableError['fe8d7103-0ea8-4ec3-814d-f8b401dc69e9'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___favorites___create': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'6dd26674-e060-4816-909a-45ba3f4da458', [x: string]: any }, - 'ALREADY_FAVORITED': {'message':'The note has already been marked as a favorite.', 'code':'ALREADY_FAVORITED', 'id':'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['6dd26674-e060-4816-909a-45ba3f4da458'], + 'ALREADY_FAVORITED': IdentifiableError['a402c12b-34dd-41d2-97d8-4d2ffd96a1a6'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___favorites___delete': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'80848a2c-398f-4343-baa9-df1d57696c56', [x: string]: any }, - 'NOT_FAVORITED': {'message':'You have not marked that note a favorite.', 'code':'NOT_FAVORITED', 'id':'b625fc69-635e-45e9-86f4-dbefbef35af5', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['80848a2c-398f-4343-baa9-df1d57696c56'], + 'NOT_FAVORITED': IdentifiableError['b625fc69-635e-45e9-86f4-dbefbef35af5'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___featured': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___global-timeline': { - 'GTL_DISABLED': {'message':'Global timeline has been disabled.', 'code':'GTL_DISABLED', 'id':'0332fc13-6ab2-4427-ae80-a9fadffd1a6b', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'GTL_DISABLED': IdentifiableError['0332fc13-6ab2-4427-ae80-a9fadffd1a6b'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___hybrid-timeline': { - 'STL_DISABLED': {'message':'Hybrid timeline has been disabled.', 'code':'STL_DISABLED', 'id':'620763f4-f621-4533-ab33-0577a1a3c342', [x: string]: any }, - 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dfaa3eb7-8002-4cb7-bcc4-1095df46656f', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'STL_DISABLED': IdentifiableError['620763f4-f621-4533-ab33-0577a1a3c342'], + 'BOTH_WITH_REPLIES_AND_WITH_FILES': IdentifiableError['dfaa3eb7-8002-4cb7-bcc4-1095df46656f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___local-timeline': { - 'LTL_DISABLED': {'message':'Local timeline has been disabled.', 'code':'LTL_DISABLED', 'id':'45a6eb02-7695-4393-b023-dd3be9aaaefd', [x: string]: any }, - 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dd9c8400-1cb5-4eef-8a31-200c5f933793', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'LTL_DISABLED': IdentifiableError['45a6eb02-7695-4393-b023-dd3be9aaaefd'], + 'BOTH_WITH_REPLIES_AND_WITH_FILES': IdentifiableError['dd9c8400-1cb5-4eef-8a31-200c5f933793'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___mentions': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___polls___recommendation': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___polls___vote': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ecafbd2e-c283-4d6d-aecb-1a0a33b75396', [x: string]: any }, - 'NO_POLL': {'message':'The note does not attach a poll.', 'code':'NO_POLL', 'id':'5f979967-52d9-4314-a911-1c673727f92f', [x: string]: any }, - 'INVALID_CHOICE': {'message':'Choice ID is invalid.', 'code':'INVALID_CHOICE', 'id':'e0cc9a04-f2e8-41e4-a5f1-4127293260cc', [x: string]: any }, - 'ALREADY_VOTED': {'message':'You have already voted.', 'code':'ALREADY_VOTED', 'id':'0963fc77-efac-419b-9424-b391608dc6d8', [x: string]: any }, - 'ALREADY_EXPIRED': {'message':'The poll is already expired.', 'code':'ALREADY_EXPIRED', 'id':'1022a357-b085-4054-9083-8f8de358337e', [x: string]: any }, - 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot vote this poll because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'85a5377e-b1e9-4617-b0b9-5bea73331e49', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['ecafbd2e-c283-4d6d-aecb-1a0a33b75396'], + 'NO_POLL': IdentifiableError['5f979967-52d9-4314-a911-1c673727f92f'], + 'INVALID_CHOICE': IdentifiableError['e0cc9a04-f2e8-41e4-a5f1-4127293260cc'], + 'ALREADY_VOTED': IdentifiableError['0963fc77-efac-419b-9424-b391608dc6d8'], + 'ALREADY_EXPIRED': IdentifiableError['1022a357-b085-4054-9083-8f8de358337e'], + 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['85a5377e-b1e9-4617-b0b9-5bea73331e49'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___reactions': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'263fff3d-d0e1-4af4-bea7-8408059b451a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['263fff3d-d0e1-4af4-bea7-8408059b451a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___reactions___create': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'033d0620-5bfe-4027-965d-980b0c85a3ea', [x: string]: any }, - 'ALREADY_REACTED': {'message':'You are already reacting to that note.', 'code':'ALREADY_REACTED', 'id':'71efcf98-86d6-4e2b-b2ad-9d032369366b', [x: string]: any }, - 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot react this note because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'20ef5475-9f38-4e4c-bd33-de6d979498ec', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['033d0620-5bfe-4027-965d-980b0c85a3ea'], + 'ALREADY_REACTED': IdentifiableError['71efcf98-86d6-4e2b-b2ad-9d032369366b'], + 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['20ef5475-9f38-4e4c-bd33-de6d979498ec'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___reactions___delete': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37', [x: string]: any }, - 'NOT_REACTED': {'message':'You are not reacting to that note.', 'code':'NOT_REACTED', 'id':'92f4426d-4196-4125-aa5b-02943e2ec8fc', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37'], + 'NOT_REACTED': IdentifiableError['92f4426d-4196-4125-aa5b-02943e2ec8fc'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___renotes': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'12908022-2e21-46cd-ba6a-3edaf6093f46', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['12908022-2e21-46cd-ba6a-3edaf6093f46'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___replies': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___search-by-tag': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___search': { - 'UNAVAILABLE': {'message':'Search of notes unavailable.', 'code':'UNAVAILABLE', 'id':'0b44998d-77aa-4427-80d0-d2c9b8523011', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'UNAVAILABLE': IdentifiableError['0b44998d-77aa-4427-80d0-d2c9b8523011'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___show': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'24fcbfc6-2e37-42b6-8388-c29b3861a08d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['24fcbfc6-2e37-42b6-8388-c29b3861a08d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___state': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___thread-muting___create': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'5ff67ada-ed3b-2e71-8e87-a1a421e177d2', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['5ff67ada-ed3b-2e71-8e87-a1a421e177d2'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___thread-muting___delete': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bddd57ac-ceb3-b29d-4334-86ea5fae481a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['bddd57ac-ceb3-b29d-4334-86ea5fae481a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___timeline': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___translate': { - 'UNAVAILABLE': {'message':'Translate of notes unavailable.', 'code':'UNAVAILABLE', 'id':'50a70314-2d8a-431b-b433-efa5cc56444c', [x: string]: any }, - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bea9b03f-36e0-49c5-a4db-627a029f8971', [x: string]: any }, - 'CANNOT_TRANSLATE_INVISIBLE_NOTE': {'message':'Cannot translate invisible note.', 'code':'CANNOT_TRANSLATE_INVISIBLE_NOTE', 'id':'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'UNAVAILABLE': IdentifiableError['50a70314-2d8a-431b-b433-efa5cc56444c'], + 'NO_SUCH_NOTE': IdentifiableError['bea9b03f-36e0-49c5-a4db-627a029f8971'], + 'CANNOT_TRANSLATE_INVISIBLE_NOTE': IdentifiableError['ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___unrenote': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'efd4a259-2442-496b-8dd7-b255aa1a160f', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['efd4a259-2442-496b-8dd7-b255aa1a160f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notes___user-list-timeline': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notifications___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notifications___flush': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notifications___mark-all-as-read': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'notifications___test-notification': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'page-push': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'4a13ad31-6729-46b4-b9af-e86b265c2e74', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['4a13ad31-6729-46b4-b9af-e86b265c2e74'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___create': { - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c', [x: string]: any }, - 'NAME_ALREADY_EXISTS': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'4650348e-301c-499a-83c9-6aa988c66bc1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FILE': IdentifiableError['b7b97489-0f66-4b12-a5ff-b21bd63f6e1c'], + 'NAME_ALREADY_EXISTS': IdentifiableError['4650348e-301c-499a-83c9-6aa988c66bc1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___delete': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'eb0c6e1d-d519-4764-9486-52a7e1c6392a', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'8b741b3e-2c22-44b3-a15f-29949aa1601e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['eb0c6e1d-d519-4764-9486-52a7e1c6392a'], + 'ACCESS_DENIED': IdentifiableError['8b741b3e-2c22-44b3-a15f-29949aa1601e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___featured': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___like': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'cc98a8a2-0dc3-4123-b198-62c71df18ed3', [x: string]: any }, - 'YOUR_PAGE': {'message':'You cannot like your page.', 'code':'YOUR_PAGE', 'id':'28800466-e6db-40f2-8fae-bf9e82aa92b8', [x: string]: any }, - 'ALREADY_LIKED': {'message':'The page has already been liked.', 'code':'ALREADY_LIKED', 'id':'d4c1edbe-7da2-4eae-8714-1acfd2d63941', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['cc98a8a2-0dc3-4123-b198-62c71df18ed3'], + 'YOUR_PAGE': IdentifiableError['28800466-e6db-40f2-8fae-bf9e82aa92b8'], + 'ALREADY_LIKED': IdentifiableError['d4c1edbe-7da2-4eae-8714-1acfd2d63941'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___show': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'222120c0-3ead-4528-811b-b96f233388d7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['222120c0-3ead-4528-811b-b96f233388d7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___unlike': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'a0d41e20-1993-40bd-890e-f6e560ae648e', [x: string]: any }, - 'NOT_LIKED': {'message':'You have not liked that page.', 'code':'NOT_LIKED', 'id':'f5e586b0-ce93-4050-b0e3-7f31af5259ee', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['a0d41e20-1993-40bd-890e-f6e560ae648e'], + 'NOT_LIKED': IdentifiableError['f5e586b0-ce93-4050-b0e3-7f31af5259ee'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pages___update': { - 'NO_SUCH_PAGE': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'21149b9e-3616-4778-9592-c4ce89f5a864', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'3c15cd52-3b4b-4274-967d-6456fc4f792b', [x: string]: any }, - 'NO_SUCH_FILE': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cfc23c7c-3887-490e-af30-0ed576703c82', [x: string]: any }, - 'NAME_ALREADY_EXISTS': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_PAGE': IdentifiableError['21149b9e-3616-4778-9592-c4ce89f5a864'], + 'ACCESS_DENIED': IdentifiableError['3c15cd52-3b4b-4274-967d-6456fc4f792b'], + 'NO_SUCH_FILE': IdentifiableError['cfc23c7c-3887-490e-af30-0ed576703c82'], + 'NAME_ALREADY_EXISTS': IdentifiableError['2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___create': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___delete': { - 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'de1623ef-bbb3-4289-a71e-14cfa83d9740', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'1036ad7b-9f92-4fff-89c3-0e50dc941704', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FLASH': IdentifiableError['de1623ef-bbb3-4289-a71e-14cfa83d9740'], + 'ACCESS_DENIED': IdentifiableError['1036ad7b-9f92-4fff-89c3-0e50dc941704'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___featured': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___like': { - 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'c07c1491-9161-4c5c-9d75-01906f911f73', [x: string]: any }, - 'YOUR_FLASH': {'message':'You cannot like your flash.', 'code':'YOUR_FLASH', 'id':'3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b', [x: string]: any }, - 'ALREADY_LIKED': {'message':'The flash has already been liked.', 'code':'ALREADY_LIKED', 'id':'010065cf-ad43-40df-8067-abff9f4686e3', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FLASH': IdentifiableError['c07c1491-9161-4c5c-9d75-01906f911f73'], + 'YOUR_FLASH': IdentifiableError['3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b'], + 'ALREADY_LIKED': IdentifiableError['010065cf-ad43-40df-8067-abff9f4686e3'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___show': { - 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'f0d34a1a-d29a-401d-90ba-1982122b5630', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FLASH': IdentifiableError['f0d34a1a-d29a-401d-90ba-1982122b5630'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___unlike': { - 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'afe8424a-a69e-432d-a5f2-2f0740c62410', [x: string]: any }, - 'NOT_LIKED': {'message':'You have not liked that flash.', 'code':'NOT_LIKED', 'id':'755f25a7-9871-4f65-9f34-51eaad9ae0ac', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FLASH': IdentifiableError['afe8424a-a69e-432d-a5f2-2f0740c62410'], + 'NOT_LIKED': IdentifiableError['755f25a7-9871-4f65-9f34-51eaad9ae0ac'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___update': { - 'NO_SUCH_FLASH': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'611e13d2-309e-419a-a5e4-e0422da39b02', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'08e60c88-5948-478e-a132-02ec701d67b2', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_FLASH': IdentifiableError['611e13d2-309e-419a-a5e4-e0422da39b02'], + 'ACCESS_DENIED': IdentifiableError['08e60c88-5948-478e-a132-02ec701d67b2'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___my': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'flash___my-likes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'ping': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'pinned-users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'promo___read': { - 'NO_SUCH_NOTE': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'d785b897-fcd3-4fe9-8fc3-b85c26e6c932', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_NOTE': IdentifiableError['d785b897-fcd3-4fe9-8fc3-b85c26e6c932'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'roles___list': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'roles___show': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de5502bf-009a-4639-86c1-fec349e46dcb', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['de5502bf-009a-4639-86c1-fec349e46dcb'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'roles___users': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'30aaaee3-4792-48dc-ab0d-cf501a575ac5', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['30aaaee3-4792-48dc-ab0d-cf501a575ac5'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'roles___notes': { - 'NO_SUCH_ROLE': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'eb70323a-df61-4dd4-ad90-89c83c7cf26e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_ROLE': IdentifiableError['eb70323a-df61-4dd4-ad90-89c83c7cf26e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'request-reset-password': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reset-db': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reset-password': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'server-info': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'stats': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'sw___show-registration': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'sw___update-registration': { - 'NO_SUCH_REGISTRATION': {'message':'No such registration.', 'code':'NO_SUCH_REGISTRATION', 'id':' b09d8066-8064-5613-efb6-0e963b21d012', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_REGISTRATION': IdentifiableError[' b09d8066-8064-5613-efb6-0e963b21d012'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'sw___register': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'sw___unregister': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'test': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'username___available': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___clips': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___followers': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27fa5435-88ab-43de-9360-387de88727cd', [x: string]: any }, - 'FORBIDDEN': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'3c6a84db-d619-26af-ca14-06232a21df8a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['27fa5435-88ab-43de-9360-387de88727cd'], + 'FORBIDDEN': IdentifiableError['3c6a84db-d619-26af-ca14-06232a21df8a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___following': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'63e4aba4-4156-4e53-be25-c9559e42d71b', [x: string]: any }, - 'FORBIDDEN': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', [x: string]: any }, - 'BIRTHDAY_DATE_FORMAT_INVALID': {'message':'Birthday date format is invalid.', 'code':'BIRTHDAY_DATE_FORMAT_INVALID', 'id':'a2b007b9-4782-4eba-abd3-93b05ed4130d', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['63e4aba4-4156-4e53-be25-c9559e42d71b'], + 'FORBIDDEN': IdentifiableError['f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba'], + 'BIRTHDAY_DATE_FORMAT_INVALID': IdentifiableError['a2b007b9-4782-4eba-abd3-93b05ed4130d'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___gallery___posts': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___get-frequently-replied-users': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e6965129-7b2a-40a4-bae2-cd84cd434822', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['e6965129-7b2a-40a4-bae2-cd84cd434822'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___featured-notes': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___create': { - 'TOO_MANY_USERLISTS': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'0cf21a28-7715-4f39-a20d-777bfdb8d138', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'TOO_MANY_USERLISTS': IdentifiableError['0cf21a28-7715-4f39-a20d-777bfdb8d138'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___delete': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'78436795-db79-42f5-b1e2-55ea2cf19166', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['78436795-db79-42f5-b1e2-55ea2cf19166'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___list': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a8af4a82-0980-4cc4-a6af-8b0ffd54465e', [x: string]: any }, - 'REMOTE_USER_NOT_ALLOWED': {'message':'Not allowed to load the remote user\'s list', 'code':'REMOTE_USER_NOT_ALLOWED', 'id':'53858f1b-3315-4a01-81b7-db9b48d4b79a', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['a8af4a82-0980-4cc4-a6af-8b0ffd54465e'], + 'REMOTE_USER_NOT_ALLOWED': IdentifiableError['53858f1b-3315-4a01-81b7-db9b48d4b79a'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___pull': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'588e7f72-c744-4a61-b180-d354e912bda2', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['7f44670e-ab16-43b8-b4c1-ccd2ee89cc02'], + 'NO_SUCH_USER': IdentifiableError['588e7f72-c744-4a61-b180-d354e912bda2'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___push': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'2214501d-ac96-4049-b717-91e42272a711', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a', [x: string]: any }, - 'ALREADY_ADDED': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'1de7c884-1595-49e9-857e-61f12f4d4fc5', [x: string]: any }, - 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'990232c5-3f9d-4d83-9f3f-ef27b6332a4b', [x: string]: any }, - 'TOO_MANY_USERS': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'2dd9752e-a338-413d-8eec-41814430989b', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['2214501d-ac96-4049-b717-91e42272a711'], + 'NO_SUCH_USER': IdentifiableError['a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a'], + 'ALREADY_ADDED': IdentifiableError['1de7c884-1595-49e9-857e-61f12f4d4fc5'], + 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['990232c5-3f9d-4d83-9f3f-ef27b6332a4b'], + 'TOO_MANY_USERS': IdentifiableError['2dd9752e-a338-413d-8eec-41814430989b'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___show': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7bc05c21-1d7a-41ae-88f1-66820f4dc686', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['7bc05c21-1d7a-41ae-88f1-66820f4dc686'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___favorite': { - 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'7dbaf3cf-7b42-4b8f-b431-b3919e580dbe', [x: string]: any }, - 'ALREADY_FAVORITED': {'message':'The list has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'6425bba0-985b-461e-af1b-518070e72081', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER_LIST': IdentifiableError['7dbaf3cf-7b42-4b8f-b431-b3919e580dbe'], + 'ALREADY_FAVORITED': IdentifiableError['6425bba0-985b-461e-af1b-518070e72081'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___unfavorite': { - 'NO_SUCH_USER_LIST': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'baedb33e-76b8-4b0c-86a8-9375c0a7b94b', [x: string]: any }, - 'ALREADY_FAVORITED': {'message':'You have not favorited the list.', 'code':'ALREADY_FAVORITED', 'id':'835c4b27-463d-4cfa-969b-a9058678d465', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER_LIST': IdentifiableError['baedb33e-76b8-4b0c-86a8-9375c0a7b94b'], + 'ALREADY_FAVORITED': IdentifiableError['835c4b27-463d-4cfa-969b-a9058678d465'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___update': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'796666fe-3dff-4d39-becb-8a5932c1d5b7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['796666fe-3dff-4d39-becb-8a5932c1d5b7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___create-from-public': { - 'TOO_MANY_USERLISTS': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'e9c105b2-c595-47de-97fb-7f7c2c33e92f', [x: string]: any }, - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'9292f798-6175-4f7d-93f4-b6742279667d', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'13c457db-a8cb-4d88-b70a-211ceeeabb5f', [x: string]: any }, - 'ALREADY_ADDED': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'c3ad6fdb-692b-47ee-a455-7bd12c7af615', [x: string]: any }, - 'YOU_HAVE_BEEN_BLOCKED': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'a2497f2a-2389-439c-8626-5298540530f4', [x: string]: any }, - 'TOO_MANY_USERS': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'1845ea77-38d1-426e-8e4e-8b83b24f5bd7', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'TOO_MANY_USERLISTS': IdentifiableError['e9c105b2-c595-47de-97fb-7f7c2c33e92f'], + 'NO_SUCH_LIST': IdentifiableError['9292f798-6175-4f7d-93f4-b6742279667d'], + 'NO_SUCH_USER': IdentifiableError['13c457db-a8cb-4d88-b70a-211ceeeabb5f'], + 'ALREADY_ADDED': IdentifiableError['c3ad6fdb-692b-47ee-a455-7bd12c7af615'], + 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['a2497f2a-2389-439c-8626-5298540530f4'], + 'TOO_MANY_USERS': IdentifiableError['1845ea77-38d1-426e-8e4e-8b83b24f5bd7'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___update-membership': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'588e7f72-c744-4a61-b180-d354e912bda2', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['7f44670e-ab16-43b8-b4c1-ccd2ee89cc02'], + 'NO_SUCH_USER': IdentifiableError['588e7f72-c744-4a61-b180-d354e912bda2'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___lists___get-memberships': { - 'NO_SUCH_LIST': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7bc05c21-1d7a-41ae-88f1-66820f4dc686', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_LIST': IdentifiableError['7bc05c21-1d7a-41ae-88f1-66820f4dc686'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___notes': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27e494ba-2ac2-48e8-893b-10d4d8c2387b', [x: string]: any }, - 'BOTH_WITH_REPLIES_AND_WITH_FILES': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'91c8cb9f-36ed-46e7-9ca2-7df96ed6e222', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['27e494ba-2ac2-48e8-893b-10d4d8c2387b'], + 'BOTH_WITH_REPLIES_AND_WITH_FILES': IdentifiableError['91c8cb9f-36ed-46e7-9ca2-7df96ed6e222'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___pages': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___flashs': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___reactions': { - 'REACTIONS_NOT_PUBLIC': {'message':'Reactions of the user is not public.', 'code':'REACTIONS_NOT_PUBLIC', 'id':'673a7dd2-6924-1093-e0c0-e68456ceae5c', [x: string]: any }, - 'IS_REMOTE_USER': {'message':'Currently unavailable to display reactions of remote users. See https://github.com/misskey-dev/misskey/issues/12964', 'code':'IS_REMOTE_USER', 'id':'6b95fa98-8cf9-2350-e284-f0ffdb54a805', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'REACTIONS_NOT_PUBLIC': IdentifiableError['673a7dd2-6924-1093-e0c0-e68456ceae5c'], + 'IS_REMOTE_USER': IdentifiableError['6b95fa98-8cf9-2350-e284-f0ffdb54a805'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___recommendation': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___relation': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___report-abuse': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'1acefcb5-0959-43fd-9685-b48305736cb5', [x: string]: any }, - 'CANNOT_REPORT_YOURSELF': {'message':'Cannot report yourself.', 'code':'CANNOT_REPORT_YOURSELF', 'id':'1e13149e-b1e8-43cf-902e-c01dbfcb202f', [x: string]: any }, - 'CANNOT_REPORT_THE_ADMIN': {'message':'Cannot report the admin.', 'code':'CANNOT_REPORT_THE_ADMIN', 'id':'35e166f5-05fb-4f87-a2d5-adb42676d48f', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['1acefcb5-0959-43fd-9685-b48305736cb5'], + 'CANNOT_REPORT_YOURSELF': IdentifiableError['1e13149e-b1e8-43cf-902e-c01dbfcb202f'], + 'CANNOT_REPORT_THE_ADMIN': IdentifiableError['35e166f5-05fb-4f87-a2d5-adb42676d48f'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___search-by-username-and-host': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___search': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___show': { - 'FAILED_TO_RESOLVE_REMOTE_USER': {'message':'Failed to resolve remote user.', 'code':'FAILED_TO_RESOLVE_REMOTE_USER', 'id':'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c', 'kind':'server', [x: string]: any }, - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4362f8dc-731f-4ad8-a694-be5a88922a24', 'httpStatusCode':404, [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'FAILED_TO_RESOLVE_REMOTE_USER': IdentifiableError['ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c'], + 'NO_SUCH_USER': IdentifiableError['4362f8dc-731f-4ad8-a694-be5a88922a24'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___achievements': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'users___update-memo': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'6fef56f3-e765-4957-88e5-c6f65329b8a5', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['6fef56f3-e765-4957-88e5-c6f65329b8a5'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'fetch-rss': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'fetch-external-resources': { - 'EXT_RESOURCE_RETURNED_INVALID_SCHEMA': {'message':'External resource returned invalid schema.', 'code':'EXT_RESOURCE_RETURNED_INVALID_SCHEMA', 'id':'bb774091-7a15-4a70-9dc5-6ac8cf125856', [x: string]: any }, - 'EXT_RESOURCE_HASH_DIDNT_MATCH': {'message':'Hash did not match.', 'code':'EXT_RESOURCE_HASH_DIDNT_MATCH', 'id':'693ba8ba-b486-40df-a174-72f8279b56a4', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'EXT_RESOURCE_RETURNED_INVALID_SCHEMA': IdentifiableError['bb774091-7a15-4a70-9dc5-6ac8cf125856'], + 'EXT_RESOURCE_HASH_DIDNT_MATCH': IdentifiableError['693ba8ba-b486-40df-a174-72f8279b56a4'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'retention': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'bubble-game___register': { - 'INVALID_SEED': {'message':'Provided seed is invalid.', 'code':'INVALID_SEED', 'id':'eb627bc7-574b-4a52-a860-3c3eae772b88', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'RATE_LIMIT_EXCEEDED': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_SEED': IdentifiableError['eb627bc7-574b-4a52-a860-3c3eae772b88'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'RATE_LIMIT_EXCEEDED': IdentifiableError['d5826d14-3982-4d2e-8011-b9e9f02499ef'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'bubble-game___ranking': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___cancel-match': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___games': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___match': { - 'NO_SUCH_USER': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'0b4f0559-b484-4e31-9581-3f73cee89b28', [x: string]: any }, - 'TARGET_IS_YOURSELF': {'message':'Target user is yourself.', 'code':'TARGET_IS_YOURSELF', 'id':'96fd7bd6-d2bc-426c-a865-d055dcd2828e', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_USER': IdentifiableError['0b4f0559-b484-4e31-9581-3f73cee89b28'], + 'TARGET_IS_YOURSELF': IdentifiableError['96fd7bd6-d2bc-426c-a865-d055dcd2828e'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___invitations': { - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___show-game': { - 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'f13a03db-fae1-46c9-87f3-43c8165419e1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_GAME': IdentifiableError['f13a03db-fae1-46c9-87f3-43c8165419e1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___surrender': { - 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'ace0b11f-e0a6-4076-a30d-e8284c81b2df', [x: string]: any }, - 'ALREADY_ENDED': {'message':'That game has already ended.', 'code':'ALREADY_ENDED', 'id':'6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d', [x: string]: any }, - 'ACCESS_DENIED': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'6e04164b-a992-4c93-8489-2123069973e1', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_GAME': IdentifiableError['ace0b11f-e0a6-4076-a30d-e8284c81b2df'], + 'ALREADY_ENDED': IdentifiableError['6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d'], + 'ACCESS_DENIED': IdentifiableError['6e04164b-a992-4c93-8489-2123069973e1'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, 'reversi___verify': { - 'NO_SUCH_GAME': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'8fb05624-b525-43dd-90f7-511852bdfeee', [x: string]: any }, - 'INVALID_PARAM': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, - 'CREDENTIAL_REQUIRED': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, - 'AUTHENTICATION_FAILED': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, - 'I_AM_AI': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, - 'INTERNAL_ERROR': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + 'NO_SUCH_GAME': IdentifiableError['8fb05624-b525-43dd-90f7-511852bdfeee'], + 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], + 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], + 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], + 'I_AM_AI': IdentifiableError['60c46cd1-f23a-46b1-bebe-5d2b73951a84'], + 'INTERNAL_ERROR': IdentifiableError['5d37dbcb-891e-41ca-a3d6-e690c97775ac'], }, }; + +export type IdentifiableError = { + '3d81ceae-475f-4600-b2a8-2bc116157532': {'message':'Invalid param.', 'code':'INVALID_PARAM', 'id':'3d81ceae-475f-4600-b2a8-2bc116157532', [x: string]: any }, + '1384574d-a912-4b81-8601-c7b1c4085df1': {'message':'Credential required.', 'code':'CREDENTIAL_REQUIRED', 'id':'1384574d-a912-4b81-8601-c7b1c4085df1', [x: string]: any }, + 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14': {'message':'Authentication failed. Please ensure your token is correct.', 'code':'AUTHENTICATION_FAILED', 'id':'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', [x: string]: any }, + '60c46cd1-f23a-46b1-bebe-5d2b73951a84': {'message':'You sent a request to Ai-chan, Misskey\'s showgirl, instead of the server.', 'code':'I_AM_AI', 'id':'60c46cd1-f23a-46b1-bebe-5d2b73951a84', [x: string]: any }, + '5d37dbcb-891e-41ca-a3d6-e690c97775ac': {'message':'Internal error occurred. Please contact us if the error persists.', 'code':'INTERNAL_ERROR', 'id':'5d37dbcb-891e-41ca-a3d6-e690c97775ac', [x: string]: any }, + '013de6a8-f757-04cb-4d73-cc2a7e3368e4': {'message':'No such recipient.', 'code':'NO_SUCH_RECIPIENT', 'id':'013de6a8-f757-04cb-4d73-cc2a7e3368e4', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + '348bb8ae-575a-6fe9-4327-5811999def8f': {'message':'If "method" is email, "userId" must be set.', 'code':'CORRELATION_CHECK_EMAIL', 'id':'348bb8ae-575a-6fe9-4327-5811999def8f', 'httpStatusCode':400, [x: string]: any }, + 'b0c15051-de2d-29ef-260c-9585cddd701a': {'message':'If "method" is webhook, "systemWebhookId" must be set.', 'code':'CORRELATION_CHECK_WEBHOOK', 'id':'b0c15051-de2d-29ef-260c-9585cddd701a', 'httpStatusCode':400, [x: string]: any }, + '7cc1d85e-2f58-fc31-b644-3de8d0d3421f': {'message':'Email address is not set.', 'code':'EMAIL_ADDRESS_NOT_SET', 'id':'7cc1d85e-2f58-fc31-b644-3de8d0d3421f', 'httpStatusCode':400, [x: string]: any }, + 'cb865949-8af5-4062-a88c-ef55e8786d1d': {'message':'No such user who has the email address.', 'code':'USER_NOT_FOUND', 'id':'cb865949-8af5-4062-a88c-ef55e8786d1d', [x: string]: any }, + 'ccac9863-3a03-416e-b899-8a64041118b1': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'ccac9863-3a03-416e-b899-8a64041118b1', [x: string]: any }, + 'b7aa1727-1354-47bc-a182-3a9c3973d300': {'message':'No such ad.', 'code':'NO_SUCH_AD', 'id':'b7aa1727-1354-47bc-a182-3a9c3973d300', [x: string]: any }, + 'ecad8040-a276-4e85-bda9-015a708d291e': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'ecad8040-a276-4e85-bda9-015a708d291e', [x: string]: any }, + 'd3aae5a7-6372-4cb4-b61c-f511ffc2d7cc': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'d3aae5a7-6372-4cb4-b61c-f511ffc2d7cc', [x: string]: any }, + 'caf3ca38-c6e5-472e-a30c-b05377dcc240': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'caf3ca38-c6e5-472e-a30c-b05377dcc240', [x: string]: any }, + 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'fc46b5a4-6b92-4c33-ac66-b806659bb5cf', [x: string]: any }, + 'f7a3462c-4e6e-4069-8421-b9bd4f4c3975': {'message':'Duplicate name.', 'code':'DUPLICATE_NAME', 'id':'f7a3462c-4e6e-4069-8421-b9bd4f4c3975', [x: string]: any }, + 'e2785b66-dca3-4087-9cac-b93c541cc425': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'e2785b66-dca3-4087-9cac-b93c541cc425', [x: string]: any }, + 'be83669b-773a-44b7-b1f8-e5e5170ac3c2': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'be83669b-773a-44b7-b1f8-e5e5170ac3c2', [x: string]: any }, + '684dec9d-a8c2-4364-9aa8-456c49cb1dc8': {'message':'No such emoji.', 'code':'NO_SUCH_EMOJI', 'id':'684dec9d-a8c2-4364-9aa8-456c49cb1dc8', [x: string]: any }, + '14fb9fd9-0731-4e2f-aeb9-f09e4740333d': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'14fb9fd9-0731-4e2f-aeb9-f09e4740333d', [x: string]: any }, + '7180fe9d-1ee3-bff9-647d-fe9896d2ffb8': {'message':'Emoji that have same name already exists.', 'code':'SAME_NAME_EMOJI_EXISTS', 'id':'7180fe9d-1ee3-bff9-647d-fe9896d2ffb8', [x: string]: any }, + 'f1380b15-3760-4c6c-a1db-5c3aaf1cbd49': {'message':'Invalid date-time format', 'code':'INVALID_DATE_TIME', 'id':'f1380b15-3760-4c6c-a1db-5c3aaf1cbd49', [x: string]: any }, + 'ee449fbe-af2a-453b-9cae-cf2fe7c895fc': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ee449fbe-af2a-453b-9cae-cf2fe7c895fc', [x: string]: any }, + 'ae427aa2-7a41-484f-a18c-2c1104051604': {'message':'The note has already promoted.', 'code':'ALREADY_PROMOTED', 'id':'ae427aa2-7a41-484f-a18c-2c1104051604', [x: string]: any }, + 'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c': {'message':'Invalid URL', 'code':'INVALID_URL', 'id':'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c', [x: string]: any }, + 'ac3794dd-2ce4-d878-e546-73c60c06b398': {'message':'No such abuse report.', 'code':'NO_SUCH_ABUSE_REPORT', 'id':'ac3794dd-2ce4-d878-e546-73c60c06b398', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + 'de0d6ecd-8e0a-4253-88ff-74bc89ae3d45': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de0d6ecd-8e0a-4253-88ff-74bc89ae3d45', [x: string]: any }, + '07dc7d34-c0d8-49b7-96c6-db3ce64ee0b3': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'07dc7d34-c0d8-49b7-96c6-db3ce64ee0b3', [x: string]: any }, + 'cd23ef55-09ad-428a-ac61-95a45e124b32': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'cd23ef55-09ad-428a-ac61-95a45e124b32', [x: string]: any }, + '6503c040-6af4-4ed9-bf07-f2dd16678eab': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6503c040-6af4-4ed9-bf07-f2dd16678eab', [x: string]: any }, + '558ea170-f653-4700-94d0-5a818371d0df': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'558ea170-f653-4700-94d0-5a818371d0df', [x: string]: any }, + '25b5bc31-dc79-4ebd-9bd2-c84978fd052c': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'25b5bc31-dc79-4ebd-9bd2-c84978fd052c', [x: string]: any }, + '6e519036-a70d-4c76-b679-bc8fb18194e2': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'6e519036-a70d-4c76-b679-bc8fb18194e2', [x: string]: any }, + '2b730f78-1179-461b-88ad-d24c9af1a5ce': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'2b730f78-1179-461b-88ad-d24c9af1a5ce', [x: string]: any }, + 'b9060ac7-5c94-4da4-9f55-2047c953df44': {'message':'Not assigned.', 'code':'NOT_ASSIGNED', 'id':'b9060ac7-5c94-4da4-9f55-2047c953df44', [x: string]: any }, + '24636eee-e8c1-493e-94b2-e16ad401e262': {'message':'Only administrators can edit members of the role.', 'code':'ACCESS_DENIED', 'id':'24636eee-e8c1-493e-94b2-e16ad401e262', [x: string]: any }, + '224eff5e-2488-4b18-b3e7-f50d94421648': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'224eff5e-2488-4b18-b3e7-f50d94421648', [x: string]: any }, + '38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d': {'message':'No such SystemWebhook.', 'code':'NO_SUCH_SYSTEM_WEBHOOK', 'id':'38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d', 'kind':'server', 'httpStatusCode':404, [x: string]: any }, + 'b57b5e1d-4f49-404a-9edb-46b00268f121': {'message':'No such announcement.', 'code':'NO_SUCH_ANNOUNCEMENT', 'id':'b57b5e1d-4f49-404a-9edb-46b00268f121', [x: string]: any }, + '95063e93-a283-4b8b-9aa5-bcdb8df69a7f': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'95063e93-a283-4b8b-9aa5-bcdb8df69a7f', [x: string]: any }, + 'faf47050-e8b5-438c-913c-db2b1576fde4': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'faf47050-e8b5-438c-913c-db2b1576fde4', [x: string]: any }, + 'b34dcf9d-348f-44bb-99d0-6c9314cfe2df': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'b34dcf9d-348f-44bb-99d0-6c9314cfe2df', [x: string]: any }, + '850926e0-fd3b-49b6-b69a-b28a5dbd82fe': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'850926e0-fd3b-49b6-b69a-b28a5dbd82fe', [x: string]: any }, + 'c06569fb-b025-4f23-b22d-1fcd20d2816b': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'c06569fb-b025-4f23-b22d-1fcd20d2816b', [x: string]: any }, + '10c673ac-8852-48eb-aa1f-f5b67f069290': {'message':'No such antenna.', 'code':'NO_SUCH_ANTENNA', 'id':'10c673ac-8852-48eb-aa1f-f5b67f069290', [x: string]: any }, + '1c6b35c9-943e-48c2-81e4-2844989407f7': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'1c6b35c9-943e-48c2-81e4-2844989407f7', [x: string]: any }, + 'd5826d14-3982-4d2e-8011-b9e9f02499ef': {'message':'Rate limit exceeded. Please try again later.', 'code':'RATE_LIMIT_EXCEEDED', 'id':'d5826d14-3982-4d2e-8011-b9e9f02499ef', [x: string]: any }, + 'dc94d745-1262-4e63-a17d-fecaa57efc82': {'message':'No such object.', 'code':'NO_SUCH_OBJECT', 'id':'dc94d745-1262-4e63-a17d-fecaa57efc82', [x: string]: any }, + 'dce83913-2dc6-4093-8a7b-71dbb11718a3': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'dce83913-2dc6-4093-8a7b-71dbb11718a3', [x: string]: any }, + '9c72d8de-391a-43c1-9d06-08d29efde8df': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'9c72d8de-391a-43c1-9d06-08d29efde8df', [x: string]: any }, + '92f93e63-428e-4f2f-a5a4-39e1407fe998': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'92f93e63-428e-4f2f-a5a4-39e1407fe998', [x: string]: any }, + 'bd72c97d-eba7-4adb-a467-f171b8847250': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'bd72c97d-eba7-4adb-a467-f171b8847250', [x: string]: any }, + 'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d': {'message':'No such app.', 'code':'NO_SUCH_APP', 'id':'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d', [x: string]: any }, + '5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3': {'message':'No such session.', 'code':'NO_SUCH_SESSION', 'id':'5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3', [x: string]: any }, + '8c8a4145-02cc-4cca-8e66-29ba60445a8e': {'message':'This session is not completed yet.', 'code':'PENDING_SESSION', 'id':'8c8a4145-02cc-4cca-8e66-29ba60445a8e', [x: string]: any }, + '7cc4f851-e2f1-4621-9633-ec9e1d00c01e': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'7cc4f851-e2f1-4621-9633-ec9e1d00c01e', [x: string]: any }, + '88b19138-f28d-42c0-8499-6a31bbd0fdc6': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'88b19138-f28d-42c0-8499-6a31bbd0fdc6', [x: string]: any }, + '787fed64-acb9-464a-82eb-afbd745b9614': {'message':'You are already blocking that user.', 'code':'ALREADY_BLOCKING', 'id':'787fed64-acb9-464a-82eb-afbd745b9614', [x: string]: any }, + '8621d8bf-c358-4303-a066-5ea78610eb3f': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'8621d8bf-c358-4303-a066-5ea78610eb3f', [x: string]: any }, + '06f6fac6-524b-473c-a354-e97a40ae6eac': {'message':'Blockee is yourself.', 'code':'BLOCKEE_IS_YOURSELF', 'id':'06f6fac6-524b-473c-a354-e97a40ae6eac', [x: string]: any }, + '291b2efa-60c6-45c0-9f6a-045c8f9b02cd': {'message':'You are not blocking that user.', 'code':'NOT_BLOCKING', 'id':'291b2efa-60c6-45c0-9f6a-045c8f9b02cd', [x: string]: any }, + 'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050', [x: string]: any }, + 'c0031718-d573-4e85-928e-10039f1fbb68': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'c0031718-d573-4e85-928e-10039f1fbb68', [x: string]: any }, + '6f6c314b-7486-4897-8966-c04a66a02923': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'6f6c314b-7486-4897-8966-c04a66a02923', [x: string]: any }, + '4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f', [x: string]: any }, + '19959ee9-0153-4c51-bbd9-a98c49dc59d6': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'19959ee9-0153-4c51-bbd9-a98c49dc59d6', [x: string]: any }, + 'f9c5467f-d492-4c3c-9a8d-a70dacc86512': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'f9c5467f-d492-4c3c-9a8d-a70dacc86512', [x: string]: any }, + '1fb7cb09-d46a-4fdf-b8df-057788cce513': {'message':'You do not have edit privilege of the channel.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fdf-b8df-057788cce513', [x: string]: any }, + 'e86c14a4-0da2-4032-8df3-e737a04c7f3b': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e86c14a4-0da2-4032-8df3-e737a04c7f3b', [x: string]: any }, + '4938f5f3-6167-4c04-9149-6607b7542861': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'4938f5f3-6167-4c04-9149-6607b7542861', [x: string]: any }, + '353c68dd-131a-476c-aa99-88a345e83668': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'353c68dd-131a-476c-aa99-88a345e83668', [x: string]: any }, + 'd6e76cc0-a1b5-4c7c-a287-73fa9c716dcf': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'d6e76cc0-a1b5-4c7c-a287-73fa9c716dcf', [x: string]: any }, + 'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b', [x: string]: any }, + '734806c4-542c-463a-9311-15c512803965': {'message':'The note has already been clipped.', 'code':'ALREADY_CLIPPED', 'id':'734806c4-542c-463a-9311-15c512803965', [x: string]: any }, + 'f0dba960-ff73-4615-8df4-d6ac5d9dc118': {'message':'You cannot add notes to the clip any more.', 'code':'TOO_MANY_CLIP_NOTES', 'id':'f0dba960-ff73-4615-8df4-d6ac5d9dc118', [x: string]: any }, + 'b80525c6-97f7-49d7-a42d-ebccd49cfd52': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b80525c6-97f7-49d7-a42d-ebccd49cfd52', [x: string]: any }, + 'aff017de-190e-434b-893e-33a9ff5049d8': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'aff017de-190e-434b-893e-33a9ff5049d8', [x: string]: any }, + '920f7c2d-6208-4b76-8082-e632020f5883': {'message':'You cannot create clip any more.', 'code':'TOO_MANY_CLIPS', 'id':'920f7c2d-6208-4b76-8082-e632020f5883', [x: string]: any }, + '70ca08ba-6865-4630-b6fb-8494759aa754': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'70ca08ba-6865-4630-b6fb-8494759aa754', [x: string]: any }, + '1d7645e6-2b6d-4635-b0fe-fe22b0e72e00': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'1d7645e6-2b6d-4635-b0fe-fe22b0e72e00', [x: string]: any }, + 'c3c5fe33-d62c-44d2-9ea5-d997703f5c20': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'c3c5fe33-d62c-44d2-9ea5-d997703f5c20', [x: string]: any }, + 'b4d92d70-b216-46fa-9a3f-a8c811699257': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'b4d92d70-b216-46fa-9a3f-a8c811699257', [x: string]: any }, + '4c2aaeae-80d8-4250-9606-26cb1fdb77a5': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'4c2aaeae-80d8-4250-9606-26cb1fdb77a5', [x: string]: any }, + '92658936-c625-4273-8326-2d790129256e': {'message':'The clip has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'92658936-c625-4273-8326-2d790129256e', [x: string]: any }, + '2603966e-b865-426c-94a7-af4a01241dc1': {'message':'No such clip.', 'code':'NO_SUCH_CLIP', 'id':'2603966e-b865-426c-94a7-af4a01241dc1', [x: string]: any }, + '90c3a9e8-b321-4dae-bf57-2bf79bbcc187': {'message':'You have not favorited the clip.', 'code':'NOT_FAVORITED', 'id':'90c3a9e8-b321-4dae-bf57-2bf79bbcc187', [x: string]: any }, + 'c118ece3-2e4b-4296-99d1-51756e32d232': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'c118ece3-2e4b-4296-99d1-51756e32d232', [x: string]: any }, + 'f449b209-0c60-4e51-84d5-29486263bfd4': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'f449b209-0c60-4e51-84d5-29486263bfd4', [x: string]: any }, + 'bec5bd69-fba3-43c9-b4fb-2894b66ad5d2': {'message':'Cannot upload the file because it has been determined that it possibly contains inappropriate content.', 'code':'INAPPROPRIATE', 'id':'bec5bd69-fba3-43c9-b4fb-2894b66ad5d2', [x: string]: any }, + 'd08dbc37-a6a9-463a-8c47-96c32ab5f064': {'message':'Cannot upload the file because you have no free space of drive.', 'code':'NO_FREE_SPACE', 'id':'d08dbc37-a6a9-463a-8c47-96c32ab5f064', [x: string]: any }, + '908939ec-e52b-4458-b395-1025195cea58': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'908939ec-e52b-4458-b395-1025195cea58', [x: string]: any }, + '5eb8d909-2540-4970-90b8-dd6f86088121': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'5eb8d909-2540-4970-90b8-dd6f86088121', [x: string]: any }, + '067bc436-2718-4795-b0fb-ecbe43949e31': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'067bc436-2718-4795-b0fb-ecbe43949e31', [x: string]: any }, + '25b73c73-68b1-41d0-bad1-381cfdf6579f': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'25b73c73-68b1-41d0-bad1-381cfdf6579f', [x: string]: any }, + '395e7156-f9f0-475e-af89-53c3c23080c2': {'message':'Invalid file name.', 'code':'INVALID_FILE_NAME', 'id':'395e7156-f9f0-475e-af89-53c3c23080c2', [x: string]: any }, + 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e7778c7e-3af9-49cd-9690-6dbc3e6c972d', [x: string]: any }, + '01a53b27-82fc-445b-a0c1-b558465a8ed2': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'01a53b27-82fc-445b-a0c1-b558465a8ed2', [x: string]: any }, + 'ea8fb7a5-af77-4a08-b608-c0218176cd73': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'ea8fb7a5-af77-4a08-b608-c0218176cd73', [x: string]: any }, + '7f59dccb-f465-75ab-5cf4-3ce44e3282f7': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'7f59dccb-f465-75ab-5cf4-3ce44e3282f7', [x: string]: any }, + '53326628-a00d-40a6-a3cd-8975105c0f95': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'53326628-a00d-40a6-a3cd-8975105c0f95', [x: string]: any }, + '1069098f-c281-440f-b085-f9932edbe091': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'1069098f-c281-440f-b085-f9932edbe091', [x: string]: any }, + 'b0fc8a17-963c-405d-bfbc-859a487295e1': {'message':'This folder has child files or folders.', 'code':'HAS_CHILD_FILES_OR_FOLDERS', 'id':'b0fc8a17-963c-405d-bfbc-859a487295e1', [x: string]: any }, + 'd74ab9eb-bb09-4bba-bf24-fb58f761e1e9': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'d74ab9eb-bb09-4bba-bf24-fb58f761e1e9', [x: string]: any }, + 'f7974dac-2c0d-4a27-926e-23583b28e98e': {'message':'No such folder.', 'code':'NO_SUCH_FOLDER', 'id':'f7974dac-2c0d-4a27-926e-23583b28e98e', [x: string]: any }, + 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1': {'message':'No such parent folder.', 'code':'NO_SUCH_PARENT_FOLDER', 'id':'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1', [x: string]: any }, + 'dbeb024837894013aed44279f9199740': {'message':'It can not be structured like nesting folders recursively.', 'code':'RECURSIVE_NESTING', 'id':'dbeb024837894013aed44279f9199740', [x: string]: any }, + 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', [x: string]: any }, + '26fbe7bb-a331-4857-af17-205b426669a9': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'26fbe7bb-a331-4857-af17-205b426669a9', [x: string]: any }, + '35387507-38c7-4cb9-9197-300b93783fa0': {'message':'You are already following that user.', 'code':'ALREADY_FOLLOWING', 'id':'35387507-38c7-4cb9-9197-300b93783fa0', [x: string]: any }, + '4e2206ec-aa4f-4960-b865-6c23ac38e2d9': {'message':'You are blocking that user.', 'code':'BLOCKING', 'id':'4e2206ec-aa4f-4960-b865-6c23ac38e2d9', [x: string]: any }, + 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0': {'message':'You are blocked by that user.', 'code':'BLOCKED', 'id':'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0', [x: string]: any }, + '5b12c78d-2b28-4dca-99d2-f56139b42ff8': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5b12c78d-2b28-4dca-99d2-f56139b42ff8', [x: string]: any }, + 'd9e400b9-36b0-4808-b1d8-79e707f1296c': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'d9e400b9-36b0-4808-b1d8-79e707f1296c', [x: string]: any }, + '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', [x: string]: any }, + '14318698-f67e-492a-99da-5353a5ac52be': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'14318698-f67e-492a-99da-5353a5ac52be', [x: string]: any }, + '4c4cbaf9-962a-463b-8418-a5e365dbf2eb': {'message':'Followee is yourself.', 'code':'FOLLOWEE_IS_YOURSELF', 'id':'4c4cbaf9-962a-463b-8418-a5e365dbf2eb', [x: string]: any }, + 'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9': {'message':'You are not following that user.', 'code':'NOT_FOLLOWING', 'id':'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9', [x: string]: any }, + 'b77e6ae6-a3e5-40da-9cc8-c240115479cc': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b77e6ae6-a3e5-40da-9cc8-c240115479cc', [x: string]: any }, + '07dc03b9-03da-422d-885b-438313707662': {'message':'Follower is yourself.', 'code':'FOLLOWER_IS_YOURSELF', 'id':'07dc03b9-03da-422d-885b-438313707662', [x: string]: any }, + '918faac3-074f-41ae-9c43-ed5d2946770d': {'message':'The other use is not following you.', 'code':'NOT_FOLLOWING', 'id':'918faac3-074f-41ae-9c43-ed5d2946770d', [x: string]: any }, + '66ce1645-d66c-46bb-8b79-96739af885bd': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'66ce1645-d66c-46bb-8b79-96739af885bd', [x: string]: any }, + 'bcde4f8b-0913-4614-8881-614e522fb041': {'message':'No follow request.', 'code':'NO_FOLLOW_REQUEST', 'id':'bcde4f8b-0913-4614-8881-614e522fb041', [x: string]: any }, + '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4e68c551-fc4c-4e46-bb41-7d4a37bf9dab', [x: string]: any }, + '089b125b-d338-482a-9a09-e2622ac9f8d4': {'message':'Follow request not found.', 'code':'FOLLOW_REQUEST_NOT_FOUND', 'id':'089b125b-d338-482a-9a09-e2622ac9f8d4', [x: string]: any }, + 'abc2ffa6-25b2-4380-ba99-321ff3a94555': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'abc2ffa6-25b2-4380-ba99-321ff3a94555', [x: string]: any }, + 'ae52f367-4bd7-4ecd-afc6-5672fff427f5': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'ae52f367-4bd7-4ecd-afc6-5672fff427f5', [x: string]: any }, + '56c06af3-1287-442f-9701-c93f7c4a62ff': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'56c06af3-1287-442f-9701-c93f7c4a62ff', [x: string]: any }, + 'f78f1511-5ebc-4478-a888-1198d752da68': {'message':'You cannot like your post.', 'code':'YOUR_POST', 'id':'f78f1511-5ebc-4478-a888-1198d752da68', [x: string]: any }, + '40e9ed56-a59c-473a-bf3f-f289c54fb5a7': {'message':'The post has already been liked.', 'code':'ALREADY_LIKED', 'id':'40e9ed56-a59c-473a-bf3f-f289c54fb5a7', [x: string]: any }, + '1137bf14-c5b0-4604-85bb-5b5371b1cd45': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'1137bf14-c5b0-4604-85bb-5b5371b1cd45', [x: string]: any }, + 'c32e6dd0-b555-4413-925e-b3757d19ed84': {'message':'No such post.', 'code':'NO_SUCH_POST', 'id':'c32e6dd0-b555-4413-925e-b3757d19ed84', [x: string]: any }, + 'e3e8e06e-be37-41f7-a5b4-87a8250288f0': {'message':'You have not liked that post.', 'code':'NOT_LIKED', 'id':'e3e8e06e-be37-41f7-a5b4-87a8250288f0', [x: string]: any }, + '110ee688-193e-4a3a-9ecf-c167b2e6981e': {'message':'No such hashtag.', 'code':'NO_SUCH_HASHTAG', 'id':'110ee688-193e-4a3a-9ecf-c167b2e6981e', [x: string]: any }, + 'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a': {'message':'User is deleted.', 'code':'USER_IS_DELETED', 'id':'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a', 'kind':'permission', [x: string]: any }, + '0d7ec6d2-e652-443e-a7bf-9ee9a0cd77b0': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'0d7ec6d2-e652-443e-a7bf-9ee9a0cd77b0', [x: string]: any }, + '798d6847-b1ed-4f9c-b1f9-163c42655995': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'798d6847-b1ed-4f9c-b1f9-163c42655995', [x: string]: any }, + 'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512': {'message':'No security key.', 'code':'NO_SECURITY_KEY', 'id':'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512', [x: string]: any }, + '652f899f-66d4-490e-993e-6606c8ec04c3': {'message':'User not found.', 'code':'USER_NOT_FOUND', 'id':'652f899f-66d4-490e-993e-6606c8ec04c3', [x: string]: any }, + '38769596-efe2-4faf-9bec-abbb3f2cd9ba': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'38769596-efe2-4faf-9bec-abbb3f2cd9ba', [x: string]: any }, + 'bf32b864-449b-47b8-974e-f9a5468546f1': {'message':'2fa not enabled.', 'code':'TWO_FACTOR_NOT_ENABLED', 'id':'bf32b864-449b-47b8-974e-f9a5468546f1', [x: string]: any }, + '78d6c839-20c9-4c66-b90a-fc0542168b48': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'78d6c839-20c9-4c66-b90a-fc0542168b48', [x: string]: any }, + 'f9c5467f-d492-4d3c-9a8g-a70dacc86512': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'f9c5467f-d492-4d3c-9a8g-a70dacc86512', [x: string]: any }, + '1fb7cb09-d46a-4fff-b8df-057708cce513': {'message':'You do not have edit privilege of this key.', 'code':'ACCESS_DENIED', 'id':'1fb7cb09-d46a-4fff-b8df-057708cce513', [x: string]: any }, + '141c598d-a825-44c8-9173-cfb9d92be493': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'141c598d-a825-44c8-9173-cfb9d92be493', [x: string]: any }, + '7add0395-9901-4098-82f9-4f67af65f775': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'7add0395-9901-4098-82f9-4f67af65f775', [x: string]: any }, + 'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e', [x: string]: any }, + 'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe', [x: string]: any }, + 'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf', [x: string]: any }, + '6f3a4dcc-f060-a707-4950-806fbdbe60d6': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'6f3a4dcc-f060-a707-4950-806fbdbe60d6', [x: string]: any }, + 'b98644cf-a5ac-4277-a502-0b8054a709a3': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b98644cf-a5ac-4277-a502-0b8054a709a3', [x: string]: any }, + '660f3599-bce0-4f95-9dde-311fd841c183': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'660f3599-bce0-4f95-9dde-311fd841c183', [x: string]: any }, + 'dee9d4ed-ad07-43ed-8b34-b2856398bc60': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'dee9d4ed-ad07-43ed-8b34-b2856398bc60', [x: string]: any }, + '31a1b42c-06f7-42ae-8a38-a661c5c9f691': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'31a1b42c-06f7-42ae-8a38-a661c5c9f691', [x: string]: any }, + 'e674141e-bd2a-ba85-e616-aefb187c9c2a': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'e674141e-bd2a-ba85-e616-aefb187c9c2a', [x: string]: any }, + '568c6e42-c86c-ba09-c004-517f83f9f1a8': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'568c6e42-c86c-ba09-c004-517f83f9f1a8', [x: string]: any }, + '9b4ada6d-d7f7-0472-0713-4f558bd1ec9c': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'9b4ada6d-d7f7-0472-0713-4f558bd1ec9c', [x: string]: any }, + 'd2f12af1-e7b4-feac-86a3-519548f2728e': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'d2f12af1-e7b4-feac-86a3-519548f2728e', [x: string]: any }, + 'ea9cc34f-c415-4bc6-a6fe-28ac40357049': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'ea9cc34f-c415-4bc6-a6fe-28ac40357049', [x: string]: any }, + 'a3c9edda-dd9b-4596-be6a-150ef813745c': {'message':'We need csv file.', 'code':'UNEXPECTED_FILE_TYPE', 'id':'a3c9edda-dd9b-4596-be6a-150ef813745c', [x: string]: any }, + 'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9': {'message':'That file is too big.', 'code':'TOO_BIG_FILE', 'id':'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9', [x: string]: any }, + '99efe367-ce6e-4d44-93f8-5fae7b040356': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'99efe367-ce6e-4d44-93f8-5fae7b040356', [x: string]: any }, + '3b71d086-c3fa-431c-b01d-ded65a777172': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'3b71d086-c3fa-431c-b01d-ded65a777172', [x: string]: any }, + 'e842c379-8ac7-4cf7-b07a-4d4de7e4671c': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e842c379-8ac7-4cf7-b07a-4d4de7e4671c', [x: string]: any }, + '7f60115d-8d93-4b0f-bd0e-3815dcbb389f': {'message':'That file is empty.', 'code':'EMPTY_FILE', 'id':'7f60115d-8d93-4b0f-bd0e-3815dcbb389f', [x: string]: any }, + '600917d4-a4cb-4cc5-8ba8-7ac8ea3c7779': {'message':'You cannot create antenna any more.', 'code':'TOO_MANY_ANTENNAS', 'id':'600917d4-a4cb-4cc5-8ba8-7ac8ea3c7779', [x: string]: any }, + '56734f8b-3928-431e-bf80-6ff87df40cb3': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'56734f8b-3928-431e-bf80-6ff87df40cb3', [x: string]: any }, + '72dab508-c64d-498f-8740-a8eec1ba385a': {'message':'You can not pin notes any more.', 'code':'PIN_LIMIT_EXCEEDED', 'id':'72dab508-c64d-498f-8740-a8eec1ba385a', [x: string]: any }, + '8b18c2b7-68fe-4edb-9892-c0cbaeb6c913': {'message':'That note has already been pinned.', 'code':'ALREADY_PINNED', 'id':'8b18c2b7-68fe-4edb-9892-c0cbaeb6c913', [x: string]: any }, + '97a1e8e7-c0f7-47d2-957a-92e61256e01a': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'97a1e8e7-c0f7-47d2-957a-92e61256e01a', [x: string]: any }, + 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a', [x: string]: any }, + '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019': {'message':'No such key.', 'code':'NO_SUCH_KEY', 'id':'1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019', [x: string]: any }, + '454170ce-9d63-4a43-9da1-ea10afe81e21': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'454170ce-9d63-4a43-9da1-ea10afe81e21', [x: string]: any }, + 'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3': {'message':'Incorrect password.', 'code':'INCORRECT_PASSWORD', 'id':'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3', [x: string]: any }, + 'a2defefb-f220-8849-0af6-17f816099323': {'message':'Unavailable email address.', 'code':'UNAVAILABLE', 'id':'a2defefb-f220-8849-0af6-17f816099323', [x: string]: any }, + '324c7a88-59f2-492f-903f-89134f93e47e': {'message':'Email address is required.', 'code':'EMAIL_REQUIRED', 'id':'324c7a88-59f2-492f-903f-89134f93e47e', [x: string]: any }, + '539f3a45-f215-4f81-a9a8-31293640207f': {'message':'No such avatar file.', 'code':'NO_SUCH_AVATAR', 'id':'539f3a45-f215-4f81-a9a8-31293640207f', [x: string]: any }, + '0d8f5629-f210-41c2-9433-735831a58595': {'message':'No such banner file.', 'code':'NO_SUCH_BANNER', 'id':'0d8f5629-f210-41c2-9433-735831a58595', [x: string]: any }, + 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191': {'message':'The file specified as an avatar is not an image.', 'code':'AVATAR_NOT_AN_IMAGE', 'id':'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191', [x: string]: any }, + '75aedb19-2afd-4e6d-87fc-67941256fa60': {'message':'The file specified as a banner is not an image.', 'code':'BANNER_NOT_AN_IMAGE', 'id':'75aedb19-2afd-4e6d-87fc-67941256fa60', [x: string]: any }, + '8e01b590-7eb9-431b-a239-860e086c408e': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'8e01b590-7eb9-431b-a239-860e086c408e', [x: string]: any }, + '0d786918-10df-41cd-8f33-8dec7d9a89a5': {'message':'Invalid Regular Expression.', 'code':'INVALID_REGEXP', 'id':'0d786918-10df-41cd-8f33-8dec7d9a89a5', [x: string]: any }, + '010665b1-a211-42d2-bc64-8f6609d79785': {'message':'Too many muted words.', 'code':'TOO_MANY_MUTED_WORDS', 'id':'010665b1-a211-42d2-bc64-8f6609d79785', [x: string]: any }, + 'bf326f31-d430-4f97-9933-5d61e4d48a23': {'message':'User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'bf326f31-d430-4f97-9933-5d61e4d48a23', [x: string]: any }, + '25c90186-4ab0-49c8-9bba-a1fa6c202ba4': {'message':'You can\'t set yourself as your own alias.', 'code':'FORBIDDEN_TO_SET_YOURSELF', 'id':'25c90186-4ab0-49c8-9bba-a1fa6c202ba4', [x: string]: any }, + '8feff0ba-5ab5-585b-31f4-4df816663fad': {'message':'This feature is restricted by your role.', 'code':'RESTRICTED_BY_ROLE', 'id':'8feff0ba-5ab5-585b-31f4-4df816663fad', [x: string]: any }, + 'b5c90186-4ab0-49c8-9bba-a1f766282ba4': {'message':'Destination account doesn\'t have proper \'Known As\' alias, or has already moved.', 'code':'DESTINATION_ACCOUNT_FORBIDS', 'id':'b5c90186-4ab0-49c8-9bba-a1f766282ba4', [x: string]: any }, + '4362e8dc-731f-4ad8-a694-be2a88922a24': {'message':'The root can\'t migrate.', 'code':'NOT_ROOT_FORBIDDEN', 'id':'4362e8dc-731f-4ad8-a694-be2a88922a24', [x: string]: any }, + '95ba11b9-90e8-43a5-ba16-7acc1ab32e71': {'message':'Local User ActivityPup URI is null.', 'code':'URI_NULL', 'id':'95ba11b9-90e8-43a5-ba16-7acc1ab32e71', [x: string]: any }, + 'b234a14e-9ebe-4581-8000-074b3c215962': {'message':'Account was already moved to another account.', 'code':'ALREADY_MOVED', 'id':'b234a14e-9ebe-4581-8000-074b3c215962', [x: string]: any }, + '87a9bb19-111e-4e37-81d3-a3e7426453b0': {'message':'You cannot create webhook any more.', 'code':'TOO_MANY_WEBHOOKS', 'id':'87a9bb19-111e-4e37-81d3-a3e7426453b0', [x: string]: any }, + '50f614d9-3047-4f7e-90d8-ad6b2d5fb098': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'50f614d9-3047-4f7e-90d8-ad6b2d5fb098', [x: string]: any }, + 'fb0fea69-da18-45b1-828d-bd4fd1612518': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'fb0fea69-da18-45b1-828d-bd4fd1612518', [x: string]: any }, + 'bae73e5a-5522-4965-ae19-3a8688e71d82': {'message':'No such webhook.', 'code':'NO_SUCH_WEBHOOK', 'id':'bae73e5a-5522-4965-ae19-3a8688e71d82', [x: string]: any }, + '8b165dd3-6f37-4557-8db1-73175d63c641': {'message':'You have exceeded the limit for creating an invitation code.', 'code':'EXCEEDED_LIMIT_OF_CREATE_INVITE_CODE', 'id':'8b165dd3-6f37-4557-8db1-73175d63c641', [x: string]: any }, + 'cd4f9ae4-7854-4e3e-8df9-c296f051e634': {'message':'No such invite code.', 'code':'NO_SUCH_INVITE_CODE', 'id':'cd4f9ae4-7854-4e3e-8df9-c296f051e634', [x: string]: any }, + 'ff17af39-000c-4d4e-abdf-848fa30fc1ce': {'message':'You can\'t delete this invite code.', 'code':'CAN_NOT_DELETE_INVITE_CODE', 'id':'ff17af39-000c-4d4e-abdf-848fa30fc1ce', [x: string]: any }, + '6fef56f3-e765-4957-88e5-c6f65329b8a5': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'6fef56f3-e765-4957-88e5-c6f65329b8a5', [x: string]: any }, + 'a4619cb2-5f23-484b-9301-94c903074e10': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'a4619cb2-5f23-484b-9301-94c903074e10', [x: string]: any }, + '7e7359cb-160c-4956-b08f-4d1c653cd007': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'7e7359cb-160c-4956-b08f-4d1c653cd007', [x: string]: any }, + 'b851d00b-8ab1-4a56-8b1b-e24187cb48ef': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'b851d00b-8ab1-4a56-8b1b-e24187cb48ef', [x: string]: any }, + 'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9', [x: string]: any }, + '5467d020-daa9-4553-81e1-135c0c35a96d': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'5467d020-daa9-4553-81e1-135c0c35a96d', [x: string]: any }, + '5e0a5dff-1e94-4202-87ae-4d9c89eb2271': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'5e0a5dff-1e94-4202-87ae-4d9c89eb2271', [x: string]: any }, + '37285718-52f7-4aef-b7de-c38b8e8a8420': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'37285718-52f7-4aef-b7de-c38b8e8a8420', [x: string]: any }, + 'ccfecbe4-1f1c-4fc2-8a3d-c3ffee61cb7b': {'message':'You are already muting that user.', 'code':'ALREADY_MUTING', 'id':'ccfecbe4-1f1c-4fc2-8a3d-c3ffee61cb7b', [x: string]: any }, + '9b6728cf-638c-4aa1-bedb-e07d8101474d': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'9b6728cf-638c-4aa1-bedb-e07d8101474d', [x: string]: any }, + '619b1314-0850-4597-a242-e245f3da42af': {'message':'Mutee is yourself.', 'code':'MUTEE_IS_YOURSELF', 'id':'619b1314-0850-4597-a242-e245f3da42af', [x: string]: any }, + '2e4ef874-8bf0-4b4b-b069-4598f6d05817': {'message':'You are not muting that user.', 'code':'NOT_MUTING', 'id':'2e4ef874-8bf0-4b4b-b069-4598f6d05817', [x: string]: any }, + '47db1a1c-b0af-458d-8fb4-986e4efafe1e': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'47db1a1c-b0af-458d-8fb4-986e4efafe1e', [x: string]: any }, + 'e1035875-9551-45ec-afa8-1ded1fcb53c8': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'e1035875-9551-45ec-afa8-1ded1fcb53c8', [x: string]: any }, + 'b5c90186-4ab0-49c8-9bba-a1f76c282ba4': {'message':'No such renote target.', 'code':'NO_SUCH_RENOTE_TARGET', 'id':'b5c90186-4ab0-49c8-9bba-a1f76c282ba4', [x: string]: any }, + 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a': {'message':'You can not Renote a pure Renote.', 'code':'CANNOT_RENOTE_TO_A_PURE_RENOTE', 'id':'fd4cc33e-2a37-48dd-99cc-9b806eb2031a', [x: string]: any }, + 'be9529e9-fe72-4de0-ae43-0b363c4938af': {'message':'You can not Renote due to target visibility.', 'code':'CANNOT_RENOTE_DUE_TO_VISIBILITY', 'id':'be9529e9-fe72-4de0-ae43-0b363c4938af', [x: string]: any }, + '749ee0f6-d3da-459a-bf02-282e2da4292c': {'message':'No such reply target.', 'code':'NO_SUCH_REPLY_TARGET', 'id':'749ee0f6-d3da-459a-bf02-282e2da4292c', [x: string]: any }, + 'b98980fa-3780-406c-a935-b6d0eeee10d1': {'message':'You cannot reply to an invisible Note.', 'code':'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE', 'id':'b98980fa-3780-406c-a935-b6d0eeee10d1', [x: string]: any }, + '3ac74a84-8fd5-4bb0-870f-01804f82ce15': {'message':'You can not reply to a pure Renote.', 'code':'CANNOT_REPLY_TO_A_PURE_RENOTE', 'id':'3ac74a84-8fd5-4bb0-870f-01804f82ce15', [x: string]: any }, + 'ed940410-535c-4d5e-bfa3-af798671e93c': {'message':'You cannot reply to a specified visibility note with extended visibility.', 'code':'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY', 'id':'ed940410-535c-4d5e-bfa3-af798671e93c', [x: string]: any }, + '04da457d-b083-4055-9082-955525eda5a5': {'message':'Poll is already expired.', 'code':'CANNOT_CREATE_ALREADY_EXPIRED_POLL', 'id':'04da457d-b083-4055-9082-955525eda5a5', [x: string]: any }, + 'b1653923-5453-4edc-b786-7c4f39bb0bbb': {'message':'No such channel.', 'code':'NO_SUCH_CHANNEL', 'id':'b1653923-5453-4edc-b786-7c4f39bb0bbb', [x: string]: any }, + 'b390d7e1-8a5e-46ed-b625-06271cafd3d3': {'message':'You have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'b390d7e1-8a5e-46ed-b625-06271cafd3d3', [x: string]: any }, + 'b6992544-63e7-67f0-fa7f-32444b1b5306': {'message':'Some files are not found.', 'code':'NO_SUCH_FILE', 'id':'b6992544-63e7-67f0-fa7f-32444b1b5306', [x: string]: any }, + '33510210-8452-094c-6227-4a6c05d99f00': {'message':'Cannot renote outside of channel.', 'code':'CANNOT_RENOTE_OUTSIDE_OF_CHANNEL', 'id':'33510210-8452-094c-6227-4a6c05d99f00', [x: string]: any }, + 'aa6e01d3-a85c-669d-758a-76aab43af334': {'message':'Cannot post because it contains prohibited words.', 'code':'CONTAINS_PROHIBITED_WORDS', 'id':'aa6e01d3-a85c-669d-758a-76aab43af334', [x: string]: any }, + '4de0363a-3046-481b-9b0f-feff3e211025': {'message':'Cannot post because it exceeds the allowed number of mentions.', 'code':'CONTAINS_TOO_MANY_MENTIONS', 'id':'4de0363a-3046-481b-9b0f-feff3e211025', [x: string]: any }, + '490be23f-8c1f-4796-819f-94cb4f9d1630': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'490be23f-8c1f-4796-819f-94cb4f9d1630', [x: string]: any }, + 'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9', [x: string]: any }, + '6dd26674-e060-4816-909a-45ba3f4da458': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'6dd26674-e060-4816-909a-45ba3f4da458', [x: string]: any }, + 'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6': {'message':'The note has already been marked as a favorite.', 'code':'ALREADY_FAVORITED', 'id':'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6', [x: string]: any }, + '80848a2c-398f-4343-baa9-df1d57696c56': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'80848a2c-398f-4343-baa9-df1d57696c56', [x: string]: any }, + 'b625fc69-635e-45e9-86f4-dbefbef35af5': {'message':'You have not marked that note a favorite.', 'code':'NOT_FAVORITED', 'id':'b625fc69-635e-45e9-86f4-dbefbef35af5', [x: string]: any }, + '0332fc13-6ab2-4427-ae80-a9fadffd1a6b': {'message':'Global timeline has been disabled.', 'code':'GTL_DISABLED', 'id':'0332fc13-6ab2-4427-ae80-a9fadffd1a6b', [x: string]: any }, + '620763f4-f621-4533-ab33-0577a1a3c342': {'message':'Hybrid timeline has been disabled.', 'code':'STL_DISABLED', 'id':'620763f4-f621-4533-ab33-0577a1a3c342', [x: string]: any }, + 'dfaa3eb7-8002-4cb7-bcc4-1095df46656f': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dfaa3eb7-8002-4cb7-bcc4-1095df46656f', [x: string]: any }, + '45a6eb02-7695-4393-b023-dd3be9aaaefd': {'message':'Local timeline has been disabled.', 'code':'LTL_DISABLED', 'id':'45a6eb02-7695-4393-b023-dd3be9aaaefd', [x: string]: any }, + 'dd9c8400-1cb5-4eef-8a31-200c5f933793': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'dd9c8400-1cb5-4eef-8a31-200c5f933793', [x: string]: any }, + 'ecafbd2e-c283-4d6d-aecb-1a0a33b75396': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'ecafbd2e-c283-4d6d-aecb-1a0a33b75396', [x: string]: any }, + '5f979967-52d9-4314-a911-1c673727f92f': {'message':'The note does not attach a poll.', 'code':'NO_POLL', 'id':'5f979967-52d9-4314-a911-1c673727f92f', [x: string]: any }, + 'e0cc9a04-f2e8-41e4-a5f1-4127293260cc': {'message':'Choice ID is invalid.', 'code':'INVALID_CHOICE', 'id':'e0cc9a04-f2e8-41e4-a5f1-4127293260cc', [x: string]: any }, + '0963fc77-efac-419b-9424-b391608dc6d8': {'message':'You have already voted.', 'code':'ALREADY_VOTED', 'id':'0963fc77-efac-419b-9424-b391608dc6d8', [x: string]: any }, + '1022a357-b085-4054-9083-8f8de358337e': {'message':'The poll is already expired.', 'code':'ALREADY_EXPIRED', 'id':'1022a357-b085-4054-9083-8f8de358337e', [x: string]: any }, + '85a5377e-b1e9-4617-b0b9-5bea73331e49': {'message':'You cannot vote this poll because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'85a5377e-b1e9-4617-b0b9-5bea73331e49', [x: string]: any }, + '263fff3d-d0e1-4af4-bea7-8408059b451a': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'263fff3d-d0e1-4af4-bea7-8408059b451a', [x: string]: any }, + '033d0620-5bfe-4027-965d-980b0c85a3ea': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'033d0620-5bfe-4027-965d-980b0c85a3ea', [x: string]: any }, + '71efcf98-86d6-4e2b-b2ad-9d032369366b': {'message':'You are already reacting to that note.', 'code':'ALREADY_REACTED', 'id':'71efcf98-86d6-4e2b-b2ad-9d032369366b', [x: string]: any }, + '20ef5475-9f38-4e4c-bd33-de6d979498ec': {'message':'You cannot react this note because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'20ef5475-9f38-4e4c-bd33-de6d979498ec', [x: string]: any }, + '764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37', [x: string]: any }, + '92f4426d-4196-4125-aa5b-02943e2ec8fc': {'message':'You are not reacting to that note.', 'code':'NOT_REACTED', 'id':'92f4426d-4196-4125-aa5b-02943e2ec8fc', [x: string]: any }, + '12908022-2e21-46cd-ba6a-3edaf6093f46': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'12908022-2e21-46cd-ba6a-3edaf6093f46', [x: string]: any }, + '0b44998d-77aa-4427-80d0-d2c9b8523011': {'message':'Search of notes unavailable.', 'code':'UNAVAILABLE', 'id':'0b44998d-77aa-4427-80d0-d2c9b8523011', [x: string]: any }, + '24fcbfc6-2e37-42b6-8388-c29b3861a08d': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'24fcbfc6-2e37-42b6-8388-c29b3861a08d', [x: string]: any }, + '5ff67ada-ed3b-2e71-8e87-a1a421e177d2': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'5ff67ada-ed3b-2e71-8e87-a1a421e177d2', [x: string]: any }, + 'bddd57ac-ceb3-b29d-4334-86ea5fae481a': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bddd57ac-ceb3-b29d-4334-86ea5fae481a', [x: string]: any }, + '50a70314-2d8a-431b-b433-efa5cc56444c': {'message':'Translate of notes unavailable.', 'code':'UNAVAILABLE', 'id':'50a70314-2d8a-431b-b433-efa5cc56444c', [x: string]: any }, + 'bea9b03f-36e0-49c5-a4db-627a029f8971': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'bea9b03f-36e0-49c5-a4db-627a029f8971', [x: string]: any }, + 'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d': {'message':'Cannot translate invisible note.', 'code':'CANNOT_TRANSLATE_INVISIBLE_NOTE', 'id':'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d', [x: string]: any }, + 'efd4a259-2442-496b-8dd7-b255aa1a160f': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'efd4a259-2442-496b-8dd7-b255aa1a160f', [x: string]: any }, + '8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff', [x: string]: any }, + '4a13ad31-6729-46b4-b9af-e86b265c2e74': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'4a13ad31-6729-46b4-b9af-e86b265c2e74', [x: string]: any }, + 'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c', [x: string]: any }, + '4650348e-301c-499a-83c9-6aa988c66bc1': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'4650348e-301c-499a-83c9-6aa988c66bc1', [x: string]: any }, + 'eb0c6e1d-d519-4764-9486-52a7e1c6392a': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'eb0c6e1d-d519-4764-9486-52a7e1c6392a', [x: string]: any }, + '8b741b3e-2c22-44b3-a15f-29949aa1601e': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'8b741b3e-2c22-44b3-a15f-29949aa1601e', [x: string]: any }, + 'cc98a8a2-0dc3-4123-b198-62c71df18ed3': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'cc98a8a2-0dc3-4123-b198-62c71df18ed3', [x: string]: any }, + '28800466-e6db-40f2-8fae-bf9e82aa92b8': {'message':'You cannot like your page.', 'code':'YOUR_PAGE', 'id':'28800466-e6db-40f2-8fae-bf9e82aa92b8', [x: string]: any }, + 'd4c1edbe-7da2-4eae-8714-1acfd2d63941': {'message':'The page has already been liked.', 'code':'ALREADY_LIKED', 'id':'d4c1edbe-7da2-4eae-8714-1acfd2d63941', [x: string]: any }, + '222120c0-3ead-4528-811b-b96f233388d7': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'222120c0-3ead-4528-811b-b96f233388d7', [x: string]: any }, + 'a0d41e20-1993-40bd-890e-f6e560ae648e': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'a0d41e20-1993-40bd-890e-f6e560ae648e', [x: string]: any }, + 'f5e586b0-ce93-4050-b0e3-7f31af5259ee': {'message':'You have not liked that page.', 'code':'NOT_LIKED', 'id':'f5e586b0-ce93-4050-b0e3-7f31af5259ee', [x: string]: any }, + '21149b9e-3616-4778-9592-c4ce89f5a864': {'message':'No such page.', 'code':'NO_SUCH_PAGE', 'id':'21149b9e-3616-4778-9592-c4ce89f5a864', [x: string]: any }, + '3c15cd52-3b4b-4274-967d-6456fc4f792b': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'3c15cd52-3b4b-4274-967d-6456fc4f792b', [x: string]: any }, + 'cfc23c7c-3887-490e-af30-0ed576703c82': {'message':'No such file.', 'code':'NO_SUCH_FILE', 'id':'cfc23c7c-3887-490e-af30-0ed576703c82', [x: string]: any }, + '2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab': {'message':'Specified name already exists.', 'code':'NAME_ALREADY_EXISTS', 'id':'2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab', [x: string]: any }, + 'de1623ef-bbb3-4289-a71e-14cfa83d9740': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'de1623ef-bbb3-4289-a71e-14cfa83d9740', [x: string]: any }, + '1036ad7b-9f92-4fff-89c3-0e50dc941704': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'1036ad7b-9f92-4fff-89c3-0e50dc941704', [x: string]: any }, + 'c07c1491-9161-4c5c-9d75-01906f911f73': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'c07c1491-9161-4c5c-9d75-01906f911f73', [x: string]: any }, + '3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b': {'message':'You cannot like your flash.', 'code':'YOUR_FLASH', 'id':'3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b', [x: string]: any }, + '010065cf-ad43-40df-8067-abff9f4686e3': {'message':'The flash has already been liked.', 'code':'ALREADY_LIKED', 'id':'010065cf-ad43-40df-8067-abff9f4686e3', [x: string]: any }, + 'f0d34a1a-d29a-401d-90ba-1982122b5630': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'f0d34a1a-d29a-401d-90ba-1982122b5630', [x: string]: any }, + 'afe8424a-a69e-432d-a5f2-2f0740c62410': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'afe8424a-a69e-432d-a5f2-2f0740c62410', [x: string]: any }, + '755f25a7-9871-4f65-9f34-51eaad9ae0ac': {'message':'You have not liked that flash.', 'code':'NOT_LIKED', 'id':'755f25a7-9871-4f65-9f34-51eaad9ae0ac', [x: string]: any }, + '611e13d2-309e-419a-a5e4-e0422da39b02': {'message':'No such flash.', 'code':'NO_SUCH_FLASH', 'id':'611e13d2-309e-419a-a5e4-e0422da39b02', [x: string]: any }, + '08e60c88-5948-478e-a132-02ec701d67b2': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'08e60c88-5948-478e-a132-02ec701d67b2', [x: string]: any }, + 'd785b897-fcd3-4fe9-8fc3-b85c26e6c932': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'d785b897-fcd3-4fe9-8fc3-b85c26e6c932', [x: string]: any }, + 'de5502bf-009a-4639-86c1-fec349e46dcb': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'de5502bf-009a-4639-86c1-fec349e46dcb', [x: string]: any }, + '30aaaee3-4792-48dc-ab0d-cf501a575ac5': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'30aaaee3-4792-48dc-ab0d-cf501a575ac5', [x: string]: any }, + 'eb70323a-df61-4dd4-ad90-89c83c7cf26e': {'message':'No such role.', 'code':'NO_SUCH_ROLE', 'id':'eb70323a-df61-4dd4-ad90-89c83c7cf26e', [x: string]: any }, + ' b09d8066-8064-5613-efb6-0e963b21d012': {'message':'No such registration.', 'code':'NO_SUCH_REGISTRATION', 'id':' b09d8066-8064-5613-efb6-0e963b21d012', [x: string]: any }, + '27fa5435-88ab-43de-9360-387de88727cd': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27fa5435-88ab-43de-9360-387de88727cd', [x: string]: any }, + '3c6a84db-d619-26af-ca14-06232a21df8a': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'3c6a84db-d619-26af-ca14-06232a21df8a', [x: string]: any }, + '63e4aba4-4156-4e53-be25-c9559e42d71b': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'63e4aba4-4156-4e53-be25-c9559e42d71b', [x: string]: any }, + 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba': {'message':'Forbidden.', 'code':'FORBIDDEN', 'id':'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', [x: string]: any }, + 'a2b007b9-4782-4eba-abd3-93b05ed4130d': {'message':'Birthday date format is invalid.', 'code':'BIRTHDAY_DATE_FORMAT_INVALID', 'id':'a2b007b9-4782-4eba-abd3-93b05ed4130d', [x: string]: any }, + 'e6965129-7b2a-40a4-bae2-cd84cd434822': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'e6965129-7b2a-40a4-bae2-cd84cd434822', [x: string]: any }, + '0cf21a28-7715-4f39-a20d-777bfdb8d138': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'0cf21a28-7715-4f39-a20d-777bfdb8d138', [x: string]: any }, + '78436795-db79-42f5-b1e2-55ea2cf19166': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'78436795-db79-42f5-b1e2-55ea2cf19166', [x: string]: any }, + 'a8af4a82-0980-4cc4-a6af-8b0ffd54465e': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a8af4a82-0980-4cc4-a6af-8b0ffd54465e', [x: string]: any }, + '53858f1b-3315-4a01-81b7-db9b48d4b79a': {'message':'Not allowed to load the remote user\'s list', 'code':'REMOTE_USER_NOT_ALLOWED', 'id':'53858f1b-3315-4a01-81b7-db9b48d4b79a', [x: string]: any }, + '7f44670e-ab16-43b8-b4c1-ccd2ee89cc02': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', [x: string]: any }, + '588e7f72-c744-4a61-b180-d354e912bda2': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'588e7f72-c744-4a61-b180-d354e912bda2', [x: string]: any }, + '2214501d-ac96-4049-b717-91e42272a711': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'2214501d-ac96-4049-b717-91e42272a711', [x: string]: any }, + 'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a', [x: string]: any }, + '1de7c884-1595-49e9-857e-61f12f4d4fc5': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'1de7c884-1595-49e9-857e-61f12f4d4fc5', [x: string]: any }, + '990232c5-3f9d-4d83-9f3f-ef27b6332a4b': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'990232c5-3f9d-4d83-9f3f-ef27b6332a4b', [x: string]: any }, + '2dd9752e-a338-413d-8eec-41814430989b': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'2dd9752e-a338-413d-8eec-41814430989b', [x: string]: any }, + '7bc05c21-1d7a-41ae-88f1-66820f4dc686': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'7bc05c21-1d7a-41ae-88f1-66820f4dc686', [x: string]: any }, + '7dbaf3cf-7b42-4b8f-b431-b3919e580dbe': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'7dbaf3cf-7b42-4b8f-b431-b3919e580dbe', [x: string]: any }, + '6425bba0-985b-461e-af1b-518070e72081': {'message':'The list has already been favorited.', 'code':'ALREADY_FAVORITED', 'id':'6425bba0-985b-461e-af1b-518070e72081', [x: string]: any }, + 'baedb33e-76b8-4b0c-86a8-9375c0a7b94b': {'message':'No such user list.', 'code':'NO_SUCH_USER_LIST', 'id':'baedb33e-76b8-4b0c-86a8-9375c0a7b94b', [x: string]: any }, + '835c4b27-463d-4cfa-969b-a9058678d465': {'message':'You have not favorited the list.', 'code':'ALREADY_FAVORITED', 'id':'835c4b27-463d-4cfa-969b-a9058678d465', [x: string]: any }, + '796666fe-3dff-4d39-becb-8a5932c1d5b7': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'796666fe-3dff-4d39-becb-8a5932c1d5b7', [x: string]: any }, + 'e9c105b2-c595-47de-97fb-7f7c2c33e92f': {'message':'You cannot create user list any more.', 'code':'TOO_MANY_USERLISTS', 'id':'e9c105b2-c595-47de-97fb-7f7c2c33e92f', [x: string]: any }, + '9292f798-6175-4f7d-93f4-b6742279667d': {'message':'No such list.', 'code':'NO_SUCH_LIST', 'id':'9292f798-6175-4f7d-93f4-b6742279667d', [x: string]: any }, + '13c457db-a8cb-4d88-b70a-211ceeeabb5f': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'13c457db-a8cb-4d88-b70a-211ceeeabb5f', [x: string]: any }, + 'c3ad6fdb-692b-47ee-a455-7bd12c7af615': {'message':'That user has already been added to that list.', 'code':'ALREADY_ADDED', 'id':'c3ad6fdb-692b-47ee-a455-7bd12c7af615', [x: string]: any }, + 'a2497f2a-2389-439c-8626-5298540530f4': {'message':'You cannot push this user because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'a2497f2a-2389-439c-8626-5298540530f4', [x: string]: any }, + '1845ea77-38d1-426e-8e4e-8b83b24f5bd7': {'message':'You can not push users any more.', 'code':'TOO_MANY_USERS', 'id':'1845ea77-38d1-426e-8e4e-8b83b24f5bd7', [x: string]: any }, + '27e494ba-2ac2-48e8-893b-10d4d8c2387b': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'27e494ba-2ac2-48e8-893b-10d4d8c2387b', [x: string]: any }, + '91c8cb9f-36ed-46e7-9ca2-7df96ed6e222': {'message':'Specifying both withReplies and withFiles is not supported', 'code':'BOTH_WITH_REPLIES_AND_WITH_FILES', 'id':'91c8cb9f-36ed-46e7-9ca2-7df96ed6e222', [x: string]: any }, + '673a7dd2-6924-1093-e0c0-e68456ceae5c': {'message':'Reactions of the user is not public.', 'code':'REACTIONS_NOT_PUBLIC', 'id':'673a7dd2-6924-1093-e0c0-e68456ceae5c', [x: string]: any }, + '6b95fa98-8cf9-2350-e284-f0ffdb54a805': {'message':'Currently unavailable to display reactions of remote users. See https://github.com/misskey-dev/misskey/issues/12964', 'code':'IS_REMOTE_USER', 'id':'6b95fa98-8cf9-2350-e284-f0ffdb54a805', [x: string]: any }, + '1acefcb5-0959-43fd-9685-b48305736cb5': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'1acefcb5-0959-43fd-9685-b48305736cb5', [x: string]: any }, + '1e13149e-b1e8-43cf-902e-c01dbfcb202f': {'message':'Cannot report yourself.', 'code':'CANNOT_REPORT_YOURSELF', 'id':'1e13149e-b1e8-43cf-902e-c01dbfcb202f', [x: string]: any }, + '35e166f5-05fb-4f87-a2d5-adb42676d48f': {'message':'Cannot report the admin.', 'code':'CANNOT_REPORT_THE_ADMIN', 'id':'35e166f5-05fb-4f87-a2d5-adb42676d48f', [x: string]: any }, + 'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c': {'message':'Failed to resolve remote user.', 'code':'FAILED_TO_RESOLVE_REMOTE_USER', 'id':'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c', 'kind':'server', [x: string]: any }, + '4362f8dc-731f-4ad8-a694-be5a88922a24': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'4362f8dc-731f-4ad8-a694-be5a88922a24', 'httpStatusCode':404, [x: string]: any }, + 'bb774091-7a15-4a70-9dc5-6ac8cf125856': {'message':'External resource returned invalid schema.', 'code':'EXT_RESOURCE_RETURNED_INVALID_SCHEMA', 'id':'bb774091-7a15-4a70-9dc5-6ac8cf125856', [x: string]: any }, + '693ba8ba-b486-40df-a174-72f8279b56a4': {'message':'Hash did not match.', 'code':'EXT_RESOURCE_HASH_DIDNT_MATCH', 'id':'693ba8ba-b486-40df-a174-72f8279b56a4', [x: string]: any }, + 'eb627bc7-574b-4a52-a860-3c3eae772b88': {'message':'Provided seed is invalid.', 'code':'INVALID_SEED', 'id':'eb627bc7-574b-4a52-a860-3c3eae772b88', [x: string]: any }, + '0b4f0559-b484-4e31-9581-3f73cee89b28': {'message':'No such user.', 'code':'NO_SUCH_USER', 'id':'0b4f0559-b484-4e31-9581-3f73cee89b28', [x: string]: any }, + '96fd7bd6-d2bc-426c-a865-d055dcd2828e': {'message':'Target user is yourself.', 'code':'TARGET_IS_YOURSELF', 'id':'96fd7bd6-d2bc-426c-a865-d055dcd2828e', [x: string]: any }, + 'f13a03db-fae1-46c9-87f3-43c8165419e1': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'f13a03db-fae1-46c9-87f3-43c8165419e1', [x: string]: any }, + 'ace0b11f-e0a6-4076-a30d-e8284c81b2df': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'ace0b11f-e0a6-4076-a30d-e8284c81b2df', [x: string]: any }, + '6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d': {'message':'That game has already ended.', 'code':'ALREADY_ENDED', 'id':'6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d', [x: string]: any }, + '6e04164b-a992-4c93-8489-2123069973e1': {'message':'Access denied.', 'code':'ACCESS_DENIED', 'id':'6e04164b-a992-4c93-8489-2123069973e1', [x: string]: any }, + '8fb05624-b525-43dd-90f7-511852bdfeee': {'message':'No such game.', 'code':'NO_SUCH_GAME', 'id':'8fb05624-b525-43dd-90f7-511852bdfeee', [x: string]: any }, +}; From 1736ee38370dcb58d110744c6dc681a8fb8241d6 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:57:37 +0900 Subject: [PATCH 05/20] fix lint --- packages/frontend/src/scripts/err-promise.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/src/scripts/err-promise.ts b/packages/frontend/src/scripts/err-promise.ts index 1bc6a386ac..2d334c3b43 100644 --- a/packages/frontend/src/scripts/err-promise.ts +++ b/packages/frontend/src/scripts/err-promise.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ - export interface IErrPromise { then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; From e7b171d6481bf028066204d80206757bbc1aa715 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:23:00 +0900 Subject: [PATCH 06/20] fix --- .../misskey-js/generator/src/generator.ts | 8 +- packages/misskey-js/src/api.ts | 4 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 764 +++++++++--------- 3 files changed, 382 insertions(+), 394 deletions(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index db8a89c34e..93a731ad34 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -290,12 +290,6 @@ async function generateApiClientJSDoc( '', ' catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;', '}', - '', - 'class ErrPromise extends Promise implements IErrPromise {', - ' constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) {', - ' super(executor);', - ' }', - '}', ); endpointOutputLine.push(''); @@ -312,7 +306,7 @@ async function generateApiClientJSDoc( ' endpoint: E,', ' params: P,', ' credential?: string | null,', - ' ): ErrPromise, RE>;', + ' ): IErrPromise, RE>;', ); if (i < endpoints.length - 1) { diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index 2727768c70..cd43d7ab37 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -65,8 +65,8 @@ export class APIClient { endpoint: E, params: P = {} as P, credential?: string | null, - ): ErrPromise, RE> { - return new Promise((resolve, reject) => { + ): IErrPromise, RE> { + return new ErrPromise((resolve, reject) => { this.fetch(`${this.origin}/api/${endpoint}`, { method: 'POST', body: JSON.stringify({ diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index 11908d0f9a..6b4f5c569e 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -7,12 +7,6 @@ interface IErrPromise { catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; } -class ErrPromise extends Promise implements IErrPromise { - constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { - super(executor); - } -} - declare module '../api.js' { export interface APIClient { /** @@ -24,7 +18,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -35,7 +29,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -47,7 +41,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -59,7 +53,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -71,7 +65,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -83,7 +77,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -95,7 +89,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -106,7 +100,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -117,7 +111,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -128,7 +122,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -139,7 +133,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -150,7 +144,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -161,7 +155,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -172,7 +166,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -183,7 +177,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -194,7 +188,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -205,7 +199,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -216,7 +210,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -227,7 +221,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -238,7 +232,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -249,7 +243,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -260,7 +254,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -271,7 +265,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -282,7 +276,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -293,7 +287,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -304,7 +298,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -315,7 +309,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -326,7 +320,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -337,7 +331,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -348,7 +342,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -359,7 +353,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -370,7 +364,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -381,7 +375,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -392,7 +386,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -404,7 +398,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -415,7 +409,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -426,7 +420,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -437,7 +431,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -448,7 +442,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -459,7 +453,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -470,7 +464,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -481,7 +475,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -492,7 +486,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -503,7 +497,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -514,7 +508,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -525,7 +519,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -536,7 +530,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -547,7 +541,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -558,7 +552,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -569,7 +563,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -580,7 +574,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -591,7 +585,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -602,7 +596,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -613,7 +607,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -624,7 +618,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -635,7 +629,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -646,7 +640,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -657,7 +651,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -668,7 +662,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -679,7 +673,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -690,7 +684,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -701,7 +695,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -712,7 +706,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -723,7 +717,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -734,7 +728,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -745,7 +739,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -756,7 +750,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -767,7 +761,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -778,7 +772,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -789,7 +783,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -800,7 +794,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -811,7 +805,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -822,7 +816,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -833,7 +827,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -844,7 +838,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -855,7 +849,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -866,7 +860,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -877,7 +871,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -888,7 +882,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -899,7 +893,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -910,7 +904,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -922,7 +916,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -934,7 +928,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -946,7 +940,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -958,7 +952,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -970,7 +964,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -981,7 +975,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -992,7 +986,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1003,7 +997,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1014,7 +1008,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1025,7 +1019,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1036,7 +1030,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1047,7 +1041,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1058,7 +1052,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1069,7 +1063,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1080,7 +1074,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1091,7 +1085,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1102,7 +1096,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1114,7 +1108,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1125,7 +1119,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1136,7 +1130,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1147,7 +1141,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1158,7 +1152,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1169,7 +1163,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1180,7 +1174,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1191,7 +1185,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1202,7 +1196,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1213,7 +1207,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1224,7 +1218,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1235,7 +1229,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1246,7 +1240,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1257,7 +1251,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1268,7 +1262,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1279,7 +1273,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1290,7 +1284,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1301,7 +1295,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1312,7 +1306,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1323,7 +1317,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1334,7 +1328,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1345,7 +1339,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1356,7 +1350,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1367,7 +1361,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1378,7 +1372,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1389,7 +1383,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1400,7 +1394,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1411,7 +1405,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1422,7 +1416,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1433,7 +1427,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1444,7 +1438,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1455,7 +1449,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1466,7 +1460,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1477,7 +1471,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1488,7 +1482,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1499,7 +1493,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1510,7 +1504,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1521,7 +1515,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1532,7 +1526,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1543,7 +1537,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1554,7 +1548,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1565,7 +1559,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1576,7 +1570,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1587,7 +1581,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1598,7 +1592,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Find the notes to which the given file is attached. @@ -1609,7 +1603,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Check if a given file exists. @@ -1620,7 +1614,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Upload a new drive file. @@ -1631,7 +1625,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Delete an existing drive file. @@ -1642,7 +1636,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Search for a drive file by a hash of the contents. @@ -1653,7 +1647,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Search for a drive file by the given parameters. @@ -1664,7 +1658,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show the properties of a drive file. @@ -1675,7 +1669,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Update the properties of a drive file. @@ -1686,7 +1680,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Request the server to download a new drive file from the specified URL. @@ -1697,7 +1691,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1708,7 +1702,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1719,7 +1713,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1730,7 +1724,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1741,7 +1735,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1752,7 +1746,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1763,7 +1757,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1774,7 +1768,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1785,7 +1779,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1796,7 +1790,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1807,7 +1801,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1819,7 +1813,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1830,7 +1824,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1841,7 +1835,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1852,7 +1846,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1863,7 +1857,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1874,7 +1868,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1885,7 +1879,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1896,7 +1890,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1907,7 +1901,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1918,7 +1912,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1929,7 +1923,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1940,7 +1934,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1951,7 +1945,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1962,7 +1956,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1973,7 +1967,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1984,7 +1978,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -1995,7 +1989,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2006,7 +2000,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2017,7 +2011,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2028,7 +2022,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2039,7 +2033,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2050,7 +2044,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2061,7 +2055,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2072,7 +2066,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2083,7 +2077,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2094,7 +2088,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2105,7 +2099,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2116,7 +2110,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2127,7 +2121,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2138,7 +2132,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2149,7 +2143,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2160,7 +2154,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2171,7 +2165,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2182,7 +2176,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2194,7 +2188,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2206,7 +2200,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2218,7 +2212,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2230,7 +2224,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2242,7 +2236,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2254,7 +2248,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2266,7 +2260,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2278,7 +2272,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2290,7 +2284,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2302,7 +2296,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2313,7 +2307,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2325,7 +2319,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2337,7 +2331,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2349,7 +2343,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2361,7 +2355,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2373,7 +2367,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2385,7 +2379,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2397,7 +2391,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2409,7 +2403,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2421,7 +2415,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2433,7 +2427,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2444,7 +2438,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2455,7 +2449,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2466,7 +2460,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2478,7 +2472,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2490,7 +2484,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2502,7 +2496,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2514,7 +2508,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2526,7 +2520,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2537,7 +2531,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2548,7 +2542,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2559,7 +2553,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2570,7 +2564,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2581,7 +2575,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2592,7 +2586,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2603,7 +2597,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2615,7 +2609,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2626,7 +2620,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2637,7 +2631,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2648,7 +2642,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2659,7 +2653,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2670,7 +2664,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2681,7 +2675,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2693,7 +2687,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2704,7 +2698,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2716,7 +2710,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2728,7 +2722,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2739,7 +2733,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2751,7 +2745,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2762,7 +2756,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2774,7 +2768,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2785,7 +2779,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2796,7 +2790,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2807,7 +2801,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2818,7 +2812,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2829,7 +2823,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2840,7 +2834,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2851,7 +2845,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2862,7 +2856,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2873,7 +2867,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2884,7 +2878,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2895,7 +2889,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2906,7 +2900,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2918,7 +2912,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2929,7 +2923,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2940,7 +2934,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2951,7 +2945,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2962,7 +2956,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2973,7 +2967,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2984,7 +2978,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -2995,7 +2989,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3006,7 +3000,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3017,7 +3011,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3028,7 +3022,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3039,7 +3033,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3050,7 +3044,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3061,7 +3055,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3072,7 +3066,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3083,7 +3077,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3094,7 +3088,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3105,7 +3099,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3116,7 +3110,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3127,7 +3121,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3138,7 +3132,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3149,7 +3143,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3160,7 +3154,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3171,7 +3165,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3182,7 +3176,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3193,7 +3187,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3204,7 +3198,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3215,7 +3209,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3226,7 +3220,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3237,7 +3231,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3248,7 +3242,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3259,7 +3253,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3270,7 +3264,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3281,7 +3275,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3292,7 +3286,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3303,7 +3297,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3314,7 +3308,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3325,7 +3319,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3336,7 +3330,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3347,7 +3341,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3358,7 +3352,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3369,7 +3363,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3381,7 +3375,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3392,7 +3386,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3403,7 +3397,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3414,7 +3408,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3425,7 +3419,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3436,7 +3430,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3447,7 +3441,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3458,7 +3452,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3469,7 +3463,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3480,7 +3474,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3491,7 +3485,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3502,7 +3496,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3513,7 +3507,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3524,7 +3518,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3535,7 +3529,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3546,7 +3540,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3557,7 +3551,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3568,7 +3562,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3579,7 +3573,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3590,7 +3584,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3601,7 +3595,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3612,7 +3606,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3623,7 +3617,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3634,7 +3628,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Request a users password to be reset. @@ -3645,7 +3639,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Only available when running with NODE_ENV=testing. Reset the database and flush Redis. @@ -3656,7 +3650,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Complete the password reset that was previously requested. @@ -3667,7 +3661,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3678,7 +3672,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3689,7 +3683,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Check push notification registration exists. @@ -3701,7 +3695,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Update push notification registration. @@ -3713,7 +3707,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Register to receive push notifications. @@ -3725,7 +3719,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Unregister from receiving push notifications. @@ -3736,7 +3730,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Endpoint for testing input validation. @@ -3747,7 +3741,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3758,7 +3752,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3769,7 +3763,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all clips this user owns. @@ -3780,7 +3774,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show everyone that follows this user. @@ -3791,7 +3785,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show everyone that this user is following. @@ -3802,7 +3796,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all gallery posts by the given user. @@ -3813,7 +3807,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Get a list of other users that the specified user frequently replies to. @@ -3824,7 +3818,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3835,7 +3829,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Create a new list of users. @@ -3846,7 +3840,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Delete an existing list of users. @@ -3857,7 +3851,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all lists that the authenticated user has created. @@ -3868,7 +3862,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Remove a user from a list. @@ -3879,7 +3873,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Add a user to an existing list. @@ -3890,7 +3884,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show the properties of a list. @@ -3901,7 +3895,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3912,7 +3906,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3923,7 +3917,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Update the properties of a list. @@ -3934,7 +3928,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3945,7 +3939,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3956,7 +3950,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3967,7 +3961,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -3978,7 +3972,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all pages this user created. @@ -3989,7 +3983,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all flashs this user created. @@ -4000,7 +3994,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show all reactions this user made. @@ -4011,7 +4005,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show users that the authenticated user might be interested to follow. @@ -4022,7 +4016,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show the different kinds of relations between the authenticated user and the specified user(s). @@ -4033,7 +4027,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * File a report. @@ -4044,7 +4038,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Search for a user by username and/or host. @@ -4055,7 +4049,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Search for users. @@ -4066,7 +4060,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * Show the properties of a user. @@ -4077,7 +4071,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4088,7 +4082,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4099,7 +4093,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4110,7 +4104,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4122,7 +4116,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4133,7 +4127,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4144,7 +4138,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4155,7 +4149,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4166,7 +4160,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4177,7 +4171,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4188,7 +4182,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4199,7 +4193,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4210,7 +4204,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4221,7 +4215,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; /** * No description provided. @@ -4232,6 +4226,6 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): IErrPromise, RE>; } } From c578015b636b8a46017b457150ab03834c4e7f0f Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:45:03 +0900 Subject: [PATCH 07/20] fix indent --- packages/misskey-js/generator/src/generator.ts | 4 ++-- packages/misskey-js/src/autogen/apiClientJSDoc.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 93a731ad34..03d17a6c45 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -286,9 +286,9 @@ async function generateApiClientJSDoc( endpointOutputLine.push( 'interface IErrPromise {', - ' then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;', + ' then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;', '', - ' catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;', + ' catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;', '}', ); endpointOutputLine.push(''); diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index 6b4f5c569e..a6bc2383d3 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -2,9 +2,9 @@ import type { SwitchCaseResponseType } from '../api.js'; import type { Endpoints } from './endpoint.js'; interface IErrPromise { - then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; + then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; - catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; + catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; } declare module '../api.js' { From ee59196663b58659f9597b2d48d15eff04501b1b Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 01:29:07 +0900 Subject: [PATCH 08/20] =?UTF-8?q?class=E3=81=AE=E5=AE=9A=E7=BE=A9=E3=82=92?= =?UTF-8?q?=E4=B8=80=E6=9C=AC=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/misskey-js/etc/misskey-js.api.md | 6 + .../misskey-js/generator/src/generator.ts | 11 +- packages/misskey-js/src/api.ts | 10 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 764 +++++++++--------- 4 files changed, 388 insertions(+), 403 deletions(-) diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index cfb9a48412..fe62be145b 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -728,6 +728,7 @@ type ApGetResponse = operations['ap___get']['responses']['200']['content']['appl declare namespace api { export { isAPIError, + ErrPromise, SwitchCaseResponseType, APIError, FetchLike, @@ -2707,6 +2708,11 @@ export { entities } // @public (undocumented) type Error_2 = components['schemas']['Error']; +// @public (undocumented) +class ErrPromise extends Promise { + constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void); +} + // @public (undocumented) type ExportCustomEmojisErrors = EndpointsErrors['export-custom-emojis'][keyof EndpointsErrors['export-custom-emojis']]; diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 03d17a6c45..4f2b5b771e 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -284,15 +284,6 @@ async function generateApiClientJSDoc( endpointOutputLine.push(`import type { Endpoints } from '${toImportPath(endpointsFileName)}';`); endpointOutputLine.push(''); - endpointOutputLine.push( - 'interface IErrPromise {', - ' then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise;', - '', - ' catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise;', - '}', - ); - endpointOutputLine.push(''); - endpointOutputLine.push(`declare module '${toImportPath(apiClientFileName)}' {`); endpointOutputLine.push(' export interface APIClient {'); for (let i = 0; i < endpoints.length; i++) { @@ -306,7 +297,7 @@ async function generateApiClientJSDoc( ' endpoint: E,', ' params: P,', ' credential?: string | null,', - ' ): IErrPromise, RE>;', + ' ): ErrPromise, RE>;', ); if (i < endpoints.length - 1) { diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index cd43d7ab37..193a5d05cb 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -3,13 +3,7 @@ import './autogen/apiClientJSDoc.js'; import { SwitchCaseResponseType } from './api.types.js'; import type { Endpoints } from './api.types.js'; -interface IErrPromise { - then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; - - catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; -} - -class ErrPromise extends Promise implements IErrPromise { +export class ErrPromise extends Promise { constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { super(executor); } @@ -65,7 +59,7 @@ export class APIClient { endpoint: E, params: P = {} as P, credential?: string | null, - ): IErrPromise, RE> { + ): ErrPromise, RE> { return new ErrPromise((resolve, reject) => { this.fetch(`${this.origin}/api/${endpoint}`, { method: 'POST', diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index a6bc2383d3..b0a5c7b190 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -1,12 +1,6 @@ import type { SwitchCaseResponseType } from '../api.js'; import type { Endpoints } from './endpoint.js'; -interface IErrPromise { - then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; - - catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; -} - declare module '../api.js' { export interface APIClient { /** @@ -18,7 +12,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -29,7 +23,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -41,7 +35,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -53,7 +47,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -65,7 +59,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -77,7 +71,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -89,7 +83,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -100,7 +94,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -111,7 +105,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -122,7 +116,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -133,7 +127,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -144,7 +138,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -155,7 +149,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -166,7 +160,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -177,7 +171,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -188,7 +182,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -199,7 +193,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -210,7 +204,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -221,7 +215,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -232,7 +226,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -243,7 +237,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -254,7 +248,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -265,7 +259,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -276,7 +270,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -287,7 +281,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -298,7 +292,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -309,7 +303,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -320,7 +314,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -331,7 +325,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -342,7 +336,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -353,7 +347,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -364,7 +358,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -375,7 +369,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -386,7 +380,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -398,7 +392,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -409,7 +403,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -420,7 +414,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -431,7 +425,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -442,7 +436,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -453,7 +447,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -464,7 +458,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -475,7 +469,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -486,7 +480,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -497,7 +491,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -508,7 +502,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -519,7 +513,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -530,7 +524,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -541,7 +535,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -552,7 +546,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -563,7 +557,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -574,7 +568,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -585,7 +579,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -596,7 +590,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -607,7 +601,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -618,7 +612,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -629,7 +623,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -640,7 +634,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -651,7 +645,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -662,7 +656,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -673,7 +667,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -684,7 +678,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -695,7 +689,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -706,7 +700,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -717,7 +711,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -728,7 +722,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -739,7 +733,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -750,7 +744,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -761,7 +755,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -772,7 +766,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -783,7 +777,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -794,7 +788,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -805,7 +799,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -816,7 +810,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -827,7 +821,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -838,7 +832,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -849,7 +843,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -860,7 +854,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -871,7 +865,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -882,7 +876,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -893,7 +887,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -904,7 +898,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -916,7 +910,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -928,7 +922,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -940,7 +934,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -952,7 +946,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -964,7 +958,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -975,7 +969,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -986,7 +980,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -997,7 +991,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1008,7 +1002,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1019,7 +1013,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1030,7 +1024,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1041,7 +1035,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1052,7 +1046,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1063,7 +1057,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1074,7 +1068,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1085,7 +1079,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1096,7 +1090,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1108,7 +1102,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1119,7 +1113,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1130,7 +1124,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1141,7 +1135,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1152,7 +1146,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1163,7 +1157,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1174,7 +1168,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1185,7 +1179,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1196,7 +1190,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1207,7 +1201,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1218,7 +1212,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1229,7 +1223,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1240,7 +1234,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1251,7 +1245,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1262,7 +1256,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1273,7 +1267,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1284,7 +1278,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1295,7 +1289,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1306,7 +1300,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1317,7 +1311,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1328,7 +1322,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1339,7 +1333,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1350,7 +1344,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1361,7 +1355,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1372,7 +1366,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1383,7 +1377,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1394,7 +1388,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1405,7 +1399,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1416,7 +1410,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1427,7 +1421,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1438,7 +1432,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1449,7 +1443,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1460,7 +1454,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1471,7 +1465,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1482,7 +1476,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1493,7 +1487,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1504,7 +1498,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1515,7 +1509,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1526,7 +1520,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1537,7 +1531,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1548,7 +1542,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1559,7 +1553,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1570,7 +1564,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1581,7 +1575,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1592,7 +1586,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Find the notes to which the given file is attached. @@ -1603,7 +1597,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Check if a given file exists. @@ -1614,7 +1608,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Upload a new drive file. @@ -1625,7 +1619,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Delete an existing drive file. @@ -1636,7 +1630,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Search for a drive file by a hash of the contents. @@ -1647,7 +1641,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Search for a drive file by the given parameters. @@ -1658,7 +1652,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show the properties of a drive file. @@ -1669,7 +1663,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Update the properties of a drive file. @@ -1680,7 +1674,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Request the server to download a new drive file from the specified URL. @@ -1691,7 +1685,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1702,7 +1696,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1713,7 +1707,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1724,7 +1718,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1735,7 +1729,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1746,7 +1740,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1757,7 +1751,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1768,7 +1762,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1779,7 +1773,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1790,7 +1784,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1801,7 +1795,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1813,7 +1807,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1824,7 +1818,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1835,7 +1829,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1846,7 +1840,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1857,7 +1851,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1868,7 +1862,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1879,7 +1873,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1890,7 +1884,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1901,7 +1895,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1912,7 +1906,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1923,7 +1917,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1934,7 +1928,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1945,7 +1939,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1956,7 +1950,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1967,7 +1961,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1978,7 +1972,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -1989,7 +1983,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2000,7 +1994,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2011,7 +2005,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2022,7 +2016,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2033,7 +2027,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2044,7 +2038,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2055,7 +2049,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2066,7 +2060,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2077,7 +2071,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2088,7 +2082,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2099,7 +2093,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2110,7 +2104,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2121,7 +2115,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2132,7 +2126,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2143,7 +2137,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2154,7 +2148,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2165,7 +2159,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2176,7 +2170,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2188,7 +2182,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2200,7 +2194,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2212,7 +2206,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2224,7 +2218,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2236,7 +2230,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2248,7 +2242,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2260,7 +2254,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2272,7 +2266,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2284,7 +2278,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2296,7 +2290,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2307,7 +2301,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2319,7 +2313,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2331,7 +2325,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2343,7 +2337,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2355,7 +2349,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2367,7 +2361,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2379,7 +2373,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2391,7 +2385,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2403,7 +2397,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2415,7 +2409,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2427,7 +2421,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2438,7 +2432,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2449,7 +2443,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2460,7 +2454,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2472,7 +2466,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2484,7 +2478,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2496,7 +2490,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2508,7 +2502,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2520,7 +2514,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2531,7 +2525,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2542,7 +2536,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2553,7 +2547,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2564,7 +2558,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2575,7 +2569,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2586,7 +2580,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2597,7 +2591,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2609,7 +2603,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2620,7 +2614,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2631,7 +2625,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2642,7 +2636,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2653,7 +2647,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2664,7 +2658,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2675,7 +2669,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2687,7 +2681,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2698,7 +2692,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2710,7 +2704,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2722,7 +2716,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2733,7 +2727,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2745,7 +2739,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2756,7 +2750,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2768,7 +2762,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2779,7 +2773,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2790,7 +2784,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2801,7 +2795,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2812,7 +2806,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2823,7 +2817,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2834,7 +2828,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2845,7 +2839,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2856,7 +2850,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2867,7 +2861,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2878,7 +2872,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2889,7 +2883,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2900,7 +2894,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2912,7 +2906,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2923,7 +2917,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2934,7 +2928,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2945,7 +2939,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2956,7 +2950,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2967,7 +2961,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2978,7 +2972,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -2989,7 +2983,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3000,7 +2994,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3011,7 +3005,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3022,7 +3016,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3033,7 +3027,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3044,7 +3038,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3055,7 +3049,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3066,7 +3060,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3077,7 +3071,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3088,7 +3082,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3099,7 +3093,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3110,7 +3104,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3121,7 +3115,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3132,7 +3126,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3143,7 +3137,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3154,7 +3148,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3165,7 +3159,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3176,7 +3170,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3187,7 +3181,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3198,7 +3192,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3209,7 +3203,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3220,7 +3214,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3231,7 +3225,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3242,7 +3236,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3253,7 +3247,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3264,7 +3258,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3275,7 +3269,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3286,7 +3280,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3297,7 +3291,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3308,7 +3302,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3319,7 +3313,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3330,7 +3324,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3341,7 +3335,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3352,7 +3346,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3363,7 +3357,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3375,7 +3369,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3386,7 +3380,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3397,7 +3391,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3408,7 +3402,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3419,7 +3413,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3430,7 +3424,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3441,7 +3435,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3452,7 +3446,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3463,7 +3457,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3474,7 +3468,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3485,7 +3479,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3496,7 +3490,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3507,7 +3501,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3518,7 +3512,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3529,7 +3523,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3540,7 +3534,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3551,7 +3545,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3562,7 +3556,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3573,7 +3567,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3584,7 +3578,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3595,7 +3589,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3606,7 +3600,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3617,7 +3611,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3628,7 +3622,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Request a users password to be reset. @@ -3639,7 +3633,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Only available when running with NODE_ENV=testing. Reset the database and flush Redis. @@ -3650,7 +3644,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Complete the password reset that was previously requested. @@ -3661,7 +3655,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3672,7 +3666,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3683,7 +3677,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Check push notification registration exists. @@ -3695,7 +3689,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Update push notification registration. @@ -3707,7 +3701,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Register to receive push notifications. @@ -3719,7 +3713,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Unregister from receiving push notifications. @@ -3730,7 +3724,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Endpoint for testing input validation. @@ -3741,7 +3735,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3752,7 +3746,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3763,7 +3757,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all clips this user owns. @@ -3774,7 +3768,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show everyone that follows this user. @@ -3785,7 +3779,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show everyone that this user is following. @@ -3796,7 +3790,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all gallery posts by the given user. @@ -3807,7 +3801,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Get a list of other users that the specified user frequently replies to. @@ -3818,7 +3812,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3829,7 +3823,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Create a new list of users. @@ -3840,7 +3834,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Delete an existing list of users. @@ -3851,7 +3845,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all lists that the authenticated user has created. @@ -3862,7 +3856,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Remove a user from a list. @@ -3873,7 +3867,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Add a user to an existing list. @@ -3884,7 +3878,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show the properties of a list. @@ -3895,7 +3889,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3906,7 +3900,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3917,7 +3911,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Update the properties of a list. @@ -3928,7 +3922,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3939,7 +3933,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3950,7 +3944,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3961,7 +3955,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -3972,7 +3966,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all pages this user created. @@ -3983,7 +3977,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all flashs this user created. @@ -3994,7 +3988,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show all reactions this user made. @@ -4005,7 +3999,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show users that the authenticated user might be interested to follow. @@ -4016,7 +4010,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show the different kinds of relations between the authenticated user and the specified user(s). @@ -4027,7 +4021,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * File a report. @@ -4038,7 +4032,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Search for a user by username and/or host. @@ -4049,7 +4043,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Search for users. @@ -4060,7 +4054,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * Show the properties of a user. @@ -4071,7 +4065,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4082,7 +4076,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4093,7 +4087,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4104,7 +4098,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4116,7 +4110,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4127,7 +4121,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4138,7 +4132,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4149,7 +4143,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4160,7 +4154,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4171,7 +4165,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4182,7 +4176,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4193,7 +4187,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4204,7 +4198,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4215,7 +4209,7 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; /** * No description provided. @@ -4226,6 +4220,6 @@ declare module '../api.js' { endpoint: E, params: P, credential?: string | null, - ): IErrPromise, RE>; + ): ErrPromise, RE>; } } From 38fb25695771b49f01dca143c300c4d927c59694 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 02:18:42 +0900 Subject: [PATCH 09/20] fix --- packages/misskey-js/generator/src/generator.ts | 5 ++++- packages/misskey-js/src/autogen/endpoint.ts | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index 4f2b5b771e..a2d87f660d 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -227,9 +227,12 @@ async function generateEndpoints( const endpointOutputLine: string[] = []; + endpointOutputLine.push('/* eslint @typescript-eslint/no-unused-vars: 0 */'); + endpointOutputLine.push(''); + endpointOutputLine.push('import type {'); endpointOutputLine.push( - ...[emptyRequest, emptyResponse, ...entities].map(it => '\t' + it.generateName() + ','), + ...[emptyRequest, emptyResponse, emptyErrors, ...entities].map(it => '\t' + it.generateName() + ','), ); endpointOutputLine.push(`} from '${toImportPath(entitiesOutputPath)}';`); endpointOutputLine.push(''); diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 957d1fb262..bedd93afc7 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -1,6 +1,9 @@ +/* eslint @typescript-eslint/no-unused-vars: 0 */ + import type { EmptyRequest, EmptyResponse, + EmptyErrors, AdminMetaResponse, AdminMetaErrors, AdminAbuseUserReportsRequest, From fa24a18ccdd4c16739a7edb18327a04310ec3dab Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 02:35:49 +0900 Subject: [PATCH 10/20] fix --- packages/frontend/src/os.ts | 8 ++++---- packages/frontend/src/scripts/err-promise.ts | 8 +------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 4eb4072b72..97e5e2b1ad 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -57,7 +57,10 @@ export function apiWithDialog< text = initialText.join('\n'); if ('code' in err && err.code != null) { - if (err.code === 'INTERNAL_ERROR') { + if (customErrors && customErrors[err.code] != null) { + title = customErrors[err.code].title; + text = customErrors[err.code].text; + } else if (err.code === 'INTERNAL_ERROR') { title = i18n.ts.internalServerError; text = i18n.ts.internalServerErrorDescription; const date = new Date().toISOString(); @@ -93,9 +96,6 @@ export function apiWithDialog< } else if (err.code === 'ROLE_PERMISSION_DENIED') { title = i18n.ts.permissionDeniedError; text = i18n.ts.permissionDeniedErrorDescription; - } else if (customErrors && customErrors[err.code] != null) { - title = customErrors[err.code].title; - text = customErrors[err.code].text; } else if (err.code.startsWith('TOO_MANY')) { title = i18n.ts.youCannotCreateAnymore; if ('id' in err && err.id != null) { diff --git a/packages/frontend/src/scripts/err-promise.ts b/packages/frontend/src/scripts/err-promise.ts index 2d334c3b43..24bed5b91b 100644 --- a/packages/frontend/src/scripts/err-promise.ts +++ b/packages/frontend/src/scripts/err-promise.ts @@ -3,14 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -export interface IErrPromise { - then(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike) | undefined | null): Promise; - - catch(onrejected?: ((reason: TError) => TResult | PromiseLike) | undefined | null): Promise; -} - /** rejectに型付けができるPromise */ -export class ErrPromise extends Promise implements IErrPromise { +export class ErrPromise extends Promise { constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { super(executor); } From f926640b3b2a84f7eaae7ef3546770129991d0b1 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 14:34:16 +0900 Subject: [PATCH 11/20] don't use ErrPromise --- .../src/components/MkAutocomplete.vue | 5 + packages/frontend/src/os.ts | 112 +- packages/frontend/src/scripts/err-promise.ts | 11 - packages/frontend/src/scripts/misskey-api.ts | 25 +- packages/misskey-js/etc/misskey-js.api.md | 34 +- .../misskey-js/generator/src/generator.ts | 4 +- packages/misskey-js/src/api.ts | 49 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 1516 ++++++++--------- .../misskey-js/src/autogen/endpointErrors.ts | 2 + 9 files changed, 885 insertions(+), 873 deletions(-) delete mode 100644 packages/frontend/src/scripts/err-promise.ts diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index 932c4ecb2e..6932927172 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -58,6 +58,7 @@ import { miLocalStorage } from '@/local-storage.js'; import { customEmojis } from '@/custom-emojis.js'; import { MFM_TAGS, MFM_PARAMS } from '@/const.js'; import { searchEmoji, EmojiDef } from '@/scripts/search-emoji.js'; +import { isAPIError } from 'misskey-js/api.js'; const lib = emojilist.filter(x => x.category !== 'flags'); @@ -206,6 +207,10 @@ function exec() { fetching.value = false; // キャッシュ sessionStorage.setItem(cacheKey, JSON.stringify(searchedUsers)); + }).catch((err) => { + if (isAPIError(err)) { + console.error(err); + } }); } } else if (props.type === 'hashtag') { diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 97e5e2b1ad..735e5dd6d7 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -24,7 +24,6 @@ import MkContextMenu from '@/components/MkContextMenu.vue'; import { MenuItem } from '@/types/menu.js'; import copyToClipboard from '@/scripts/copy-to-clipboard.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; -import { ErrPromise } from '@/scripts/err-promise.js'; export const openingWindowsCount = ref(0); @@ -43,7 +42,7 @@ export function apiWithDialog< customErrors?: CustomErrorDef, ) { const promise = misskeyApi(endpoint, data, token); - promiseDialog(promise, null, async (err) => { + promiseDialog(promise, null, async (err: Error) => { let title: string | undefined; let text: string; @@ -51,57 +50,63 @@ export function apiWithDialog< if ('message' in err && err.message != null) { initialText.push(err.message); } - if ('id' in err && err.id != null) { - initialText.push(err.id); + if (Misskey.api.isAPIError(err) && 'id' in err.payload && err.payload.id != null) { + initialText.push(err.payload.id); } text = initialText.join('\n'); - if ('code' in err && err.code != null) { - if (customErrors && customErrors[err.code] != null) { - title = customErrors[err.code].title; - text = customErrors[err.code].text; - } else if (err.code === 'INTERNAL_ERROR') { - title = i18n.ts.internalServerError; - text = i18n.ts.internalServerErrorDescription; - const date = new Date().toISOString(); - const { result } = await actions({ - type: 'error', - title, - text, - actions: [{ - value: 'ok', - text: i18n.ts.gotIt, - primary: true, - }, { - value: 'copy', - text: i18n.ts.copyErrorInfo, - }], - }); - if (result === 'copy') { - const text = [ - `Endpoint: ${endpoint}`, - ('info' in err) ? `Info: ${JSON.stringify(err.info)}` : undefined, - `Date: ${date}`, - ].filter(x => x != null); - copyToClipboard(text.join('\n')); - success(); - } - return; - } else if (err.code === 'RATE_LIMIT_EXCEEDED') { - title = i18n.ts.cannotPerformTemporary; - text = i18n.ts.cannotPerformTemporaryDescription; - } else if (err.code === 'INVALID_PARAM') { - title = i18n.ts.invalidParamError; - text = i18n.ts.invalidParamErrorDescription; - } else if (err.code === 'ROLE_PERMISSION_DENIED') { - title = i18n.ts.permissionDeniedError; - text = i18n.ts.permissionDeniedErrorDescription; - } else if (err.code.startsWith('TOO_MANY')) { - title = i18n.ts.youCannotCreateAnymore; - if ('id' in err && err.id != null) { - text = `${i18n.ts.error}: ${err.id}`; - } else { - text = `${i18n.ts.error}`; + if (Misskey.api.isAPIError(err)) { + const { payload } = err; + if ('code' in payload && payload.code != null) { + if (customErrors && customErrors[payload.code] != null) { + title = customErrors[payload.code].title; + text = customErrors[payload.code].text; + } else if (payload.code === 'INTERNAL_ERROR') { + title = i18n.ts.internalServerError; + text = i18n.ts.internalServerErrorDescription; + const date = new Date().toISOString(); + const { result } = await actions({ + type: 'error', + title, + text, + actions: [{ + value: 'ok', + text: i18n.ts.gotIt, + primary: true, + }, { + value: 'copy', + text: i18n.ts.copyErrorInfo, + }], + }); + if (result === 'copy') { + const text = [ + `Endpoint: ${endpoint}`, + ('info' in err) ? `Info: ${JSON.stringify(err.info)}` : undefined, + `Date: ${date}`, + ].filter(x => x != null); + copyToClipboard(text.join('\n')); + success(); + } + return; + } else if (payload.code === 'RATE_LIMIT_EXCEEDED') { + title = i18n.ts.cannotPerformTemporary; + text = i18n.ts.cannotPerformTemporaryDescription; + } else if (payload.code === 'INVALID_PARAM') { + title = i18n.ts.invalidParamError; + text = i18n.ts.invalidParamErrorDescription; + } else if (payload.code === 'ROLE_PERMISSION_DENIED') { + title = i18n.ts.permissionDeniedError; + text = i18n.ts.permissionDeniedErrorDescription; + } else if (payload.code.startsWith('TOO_MANY')) { + title = i18n.ts.youCannotCreateAnymore; + if ('id' in err && err.id != null) { + text = `${i18n.ts.error}: ${err.id}`; + } else { + text = `${i18n.ts.error}`; + } + } else if (err.message.startsWith('Unexpected token')) { + title = i18n.ts.gotInvalidResponseError; + text = i18n.ts.gotInvalidResponseErrorDescription; } } else if (err.message.startsWith('Unexpected token')) { title = i18n.ts.gotInvalidResponseError; @@ -119,13 +124,12 @@ export function apiWithDialog< } export function promiseDialog< - T extends ErrPromise | Promise, - R = T extends ErrPromise ? R : T extends Promise ? R : never, - E = T extends ErrPromise ? E : T extends Promise ? any : never, + T extends Promise, + R = T extends Promise ? R : never, >( promise: T, onSuccess?: ((res: R) => void) | null, - onFailure?: ((err: E) => void) | null, + onFailure?: ((err: any) => void) | null, text?: string, ): T { const showing = ref(true); diff --git a/packages/frontend/src/scripts/err-promise.ts b/packages/frontend/src/scripts/err-promise.ts deleted file mode 100644 index 24bed5b91b..0000000000 --- a/packages/frontend/src/scripts/err-promise.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -/** rejectに型付けができるPromise */ -export class ErrPromise extends Promise { - constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { - super(executor); - } -} diff --git a/packages/frontend/src/scripts/misskey-api.ts b/packages/frontend/src/scripts/misskey-api.ts index 46d1e049f8..2a2db048ca 100644 --- a/packages/frontend/src/scripts/misskey-api.ts +++ b/packages/frontend/src/scripts/misskey-api.ts @@ -7,7 +7,6 @@ import * as Misskey from 'misskey-js'; import { ref } from 'vue'; import { apiUrl } from '@/config.js'; import { $i } from '@/account.js'; -import { ErrPromise } from '@/scripts/err-promise.js'; export const pendingApiRequestsCount = ref(0); // Implements Misskey.api.ApiClient.request @@ -15,14 +14,14 @@ export function misskeyApi< ResT = void, E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], - RE extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], + ER extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, >( endpoint: E, data: P = {} as any, token?: string | null | undefined, signal?: AbortSignal, -): ErrPromise<_ResT, RE> { +): Promise<_ResT> { if (endpoint.includes('://')) throw new Error('invalid endpoint'); pendingApiRequestsCount.value++; @@ -30,7 +29,7 @@ export function misskeyApi< pendingApiRequestsCount.value--; }; - const promise = new ErrPromise<_ResT, RE>((resolve, reject) => { + const promise = new Promise<_ResT>((resolve, reject) => { // Append a credential if ($i) (data as any).i = $i.token; if (token !== undefined) (data as any).i = token; @@ -53,9 +52,11 @@ export function misskeyApi< } else if (res.status === 204) { resolve(undefined as _ResT); // void -> undefined } else { - reject(body.error); + reject(new Misskey.api.APIError(body.error)); } - }).catch(reject); + }).catch((reason) => { + reject(new Error(reason)); + }); }); promise.then(onFinally, onFinally); @@ -68,12 +69,12 @@ export function misskeyApiGet< ResT = void, E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], - RE extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], + ER extends Misskey.Endpoints[E]['errors'] = Misskey.Endpoints[E]['errors'], _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, >( endpoint: E, data: P = {} as any, -): ErrPromise<_ResT, RE> { +): Promise<_ResT> { pendingApiRequestsCount.value++; const onFinally = () => { @@ -82,7 +83,7 @@ export function misskeyApiGet< const query = new URLSearchParams(data as any); - const promise = new ErrPromise<_ResT, RE>((resolve, reject) => { + const promise = new Promise<_ResT>((resolve, reject) => { // Send request window.fetch(`${apiUrl}/${endpoint}?${query}`, { method: 'GET', @@ -96,9 +97,11 @@ export function misskeyApiGet< } else if (res.status === 204) { resolve(undefined as _ResT); // void -> undefined } else { - reject(body.error); + reject(new Misskey.api.APIError(body.error)); } - }).catch(reject); + }).catch((reason) => { + reject(new Error(reason)); + }); }); promise.then(onFinally, onFinally); diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index fe62be145b..3512140873 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -728,7 +728,6 @@ type ApGetResponse = operations['ap___get']['responses']['200']['content']['appl declare namespace api { export { isAPIError, - ErrPromise, SwitchCaseResponseType, APIError, FetchLike, @@ -753,13 +752,25 @@ class APIClient { } // @public (undocumented) -type APIError = { - id: string; - code: string; - message: string; - kind: 'client' | 'server'; - info: Record; -}; +class APIError extends Error { + // (undocumented) + readonly [MK_API_ERROR] = true; + constructor(response: ER extends Record ? { + id: string; + code: string; + message: string; + kind: 'client' | 'server'; + info: Record; + } : ER); + // (undocumented) + payload: ER extends Record ? { + id: string; + code: string; + message: string; + kind: "client" | "server"; + info: Record; + } : ER; +} // @public (undocumented) type App = components['schemas']['App']; @@ -2708,11 +2719,6 @@ export { entities } // @public (undocumented) type Error_2 = components['schemas']['Error']; -// @public (undocumented) -class ErrPromise extends Promise { - constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void); -} - // @public (undocumented) type ExportCustomEmojisErrors = EndpointsErrors['export-custom-emojis'][keyof EndpointsErrors['export-custom-emojis']]; @@ -3448,7 +3454,7 @@ type IRevokeTokenErrors = EndpointsErrors['i___revoke-token'][keyof EndpointsErr type IRevokeTokenRequest = operations['i___revoke-token']['requestBody']['content']['application/json']; // @public (undocumented) -function isAPIError(reason: Record): reason is APIError; +function isAPIError(reason: any): reason is APIError; // @public (undocumented) type ISigninHistoryErrors = EndpointsErrors['i___signin-history'][keyof EndpointsErrors['i___signin-history']]; diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index a2d87f660d..37297488be 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -296,11 +296,11 @@ async function generateApiClientJSDoc( ' /**', ` * ${endpoint.description.split('\n').join('\n * ')}`, ' */', - ` request(`, + ` request(`, ' endpoint: E,', ' params: P,', ' credential?: string | null,', - ' ): ErrPromise, RE>;', + ' ): Promise>;', ); if (i < endpoints.length - 1) { diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index 193a5d05cb..0406bfa1d3 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -3,28 +3,31 @@ import './autogen/apiClientJSDoc.js'; import { SwitchCaseResponseType } from './api.types.js'; import type { Endpoints } from './api.types.js'; -export class ErrPromise extends Promise { - constructor(executor: (resolve: (value: TSuccess | PromiseLike) => void, reject: (reason: TError) => void) => void) { - super(executor); - } -} - export type { SwitchCaseResponseType, } from './api.types.js'; const MK_API_ERROR = Symbol(); -export type APIError = { - id: string; - code: string; - message: string; - kind: 'client' | 'server'; - info: Record; -}; +export class APIError extends Error { -export function isAPIError(reason: Record): reason is APIError { - return reason[MK_API_ERROR] === true; + public payload; + public readonly [MK_API_ERROR] = true; + + constructor(response: ER extends Record ? { + id: string; + code: string; + message: string; + kind: 'client' | 'server'; + info: Record; + } : ER) { + super('message' in response ? response.message : 'API Error'); + this.payload = response; + } +} + +export function isAPIError(reason: any): reason is APIError { + return reason instanceof Error && MK_API_ERROR in reason; } export type FetchLike = (input: string, init?: { @@ -55,12 +58,13 @@ export class APIClient { this.fetch = opts.fetch ?? ((...args) => fetch(...args)); } - public request( + + public request( endpoint: E, params: P = {} as P, credential?: string | null, - ): ErrPromise, RE> { - return new ErrPromise((resolve, reject) => { + ): Promise> { + return new Promise((resolve, reject) => { this.fetch(`${this.origin}/api/${endpoint}`, { method: 'POST', body: JSON.stringify({ @@ -78,12 +82,11 @@ export class APIClient { if (res.status === 200 || res.status === 204) { resolve(body); } else { - reject({ - [MK_API_ERROR]: true, - ...body.error, - }); + reject(new APIError(body.error)); } - }).catch(reject); + }).catch((reason) => { + reject(new Error(reason)); + }); }); } } diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index b0a5c7b190..e799d4a0c5 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -8,22 +8,22 @@ declare module '../api.js' { * * **Credential required**: *Yes* / **Permission**: *read:admin:meta* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-user-reports* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -31,11 +31,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -43,11 +43,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -55,11 +55,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -67,11 +67,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -79,308 +79,308 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:avatar-decorations* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:delete-all-files-of-a-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unset-user-avatar* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unset-user-banner* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -388,517 +388,517 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:index-stats* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:table-stats* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:user-ips* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:promo* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:queue* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:emoji* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:relays* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:reset-password* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:resolve-abuse-user-report* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:send-email* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:server-info* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-moderation-log* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:show-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:suspend-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:unsuspend-user* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:meta* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:delete-account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:user-note* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:admin:roles* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -906,11 +906,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -918,11 +918,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -930,11 +930,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -942,11 +942,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -954,143 +954,143 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:federation* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -1098,704 +1098,704 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:blocks* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:channels* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:clip-favorite* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Find the notes to which the given file is attached. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Check if a given file exists. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Upload a new drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Delete an existing drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Search for a drive file by a hash of the contents. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Search for a drive file by the given parameters. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show the properties of a drive file. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Update the properties of a drive file. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Request the server to download a new drive file from the specified URL. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:drive* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -1803,374 +1803,374 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:following* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2178,11 +2178,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2190,11 +2190,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2202,11 +2202,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2214,11 +2214,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2226,11 +2226,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2238,11 +2238,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2250,11 +2250,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2262,11 +2262,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2274,11 +2274,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2286,22 +2286,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2309,11 +2309,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2321,11 +2321,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2333,11 +2333,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2345,11 +2345,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2357,11 +2357,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2369,11 +2369,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2381,11 +2381,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2393,11 +2393,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2405,11 +2405,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2417,44 +2417,44 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:gallery-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:gallery* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2462,11 +2462,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2474,11 +2474,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2486,11 +2486,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2498,11 +2498,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2510,88 +2510,88 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2599,77 +2599,77 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2677,22 +2677,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2700,11 +2700,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2712,22 +2712,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2735,22 +2735,22 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2758,143 +2758,143 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:invite-codes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -2902,462 +2902,462 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:mutes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:favorites* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:votes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:reactions* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:reactions* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:notifications* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -3365,319 +3365,319 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:page-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:pages* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:flash* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:flash-likes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Request a users password to be reset. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Only available when running with NODE_ENV=testing. Reset the database and flush Redis. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Complete the password reset that was previously requested. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Check push notification registration exists. @@ -3685,11 +3685,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Update push notification registration. @@ -3697,11 +3697,11 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Register to receive push notifications. @@ -3709,396 +3709,396 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Unregister from receiving push notifications. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Endpoint for testing input validation. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all clips this user owns. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show everyone that follows this user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show everyone that this user is following. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all gallery posts by the given user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Get a list of other users that the specified user frequently replies to. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Create a new list of users. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Delete an existing list of users. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all lists that the authenticated user has created. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Remove a user from a list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Add a user to an existing list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show the properties of a list. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Update the properties of a list. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all pages this user created. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all flashs this user created. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show all reactions this user made. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show users that the authenticated user might be interested to follow. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show the different kinds of relations between the authenticated user and the specified user(s). * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * File a report. * * **Credential required**: *Yes* / **Permission**: *write:report-abuse* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Search for a user by username and/or host. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Search for users. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * Show the properties of a user. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. @@ -4106,120 +4106,120 @@ declare module '../api.js' { * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. * **Credential required**: *Yes* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *read:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *Yes* / **Permission**: *write:account* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; /** * No description provided. * * **Credential required**: *No* */ - request( + request( endpoint: E, params: P, credential?: string | null, - ): ErrPromise, RE>; + ): Promise>; } } diff --git a/packages/misskey-js/src/autogen/endpointErrors.ts b/packages/misskey-js/src/autogen/endpointErrors.ts index 29e5eb028f..4ca8cfab7a 100644 --- a/packages/misskey-js/src/autogen/endpointErrors.ts +++ b/packages/misskey-js/src/autogen/endpointErrors.ts @@ -2271,6 +2271,7 @@ export type EndpointsErrors = { 'NO_SUCH_NOTE': IdentifiableError['033d0620-5bfe-4027-965d-980b0c85a3ea'], 'ALREADY_REACTED': IdentifiableError['71efcf98-86d6-4e2b-b2ad-9d032369366b'], 'YOU_HAVE_BEEN_BLOCKED': IdentifiableError['20ef5475-9f38-4e4c-bd33-de6d979498ec'], + 'CANNOT_REACT_TO_RENOTE': IdentifiableError['eaccdc08-ddef-43fe-908f-d108faad57f5'], 'INVALID_PARAM': IdentifiableError['3d81ceae-475f-4600-b2a8-2bc116157532'], 'CREDENTIAL_REQUIRED': IdentifiableError['1384574d-a912-4b81-8601-c7b1c4085df1'], 'AUTHENTICATION_FAILED': IdentifiableError['b0a7f5f8-dc2f-4171-b91f-de88ad238e14'], @@ -3298,6 +3299,7 @@ export type IdentifiableError = { '033d0620-5bfe-4027-965d-980b0c85a3ea': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'033d0620-5bfe-4027-965d-980b0c85a3ea', [x: string]: any }, '71efcf98-86d6-4e2b-b2ad-9d032369366b': {'message':'You are already reacting to that note.', 'code':'ALREADY_REACTED', 'id':'71efcf98-86d6-4e2b-b2ad-9d032369366b', [x: string]: any }, '20ef5475-9f38-4e4c-bd33-de6d979498ec': {'message':'You cannot react this note because you have been blocked by this user.', 'code':'YOU_HAVE_BEEN_BLOCKED', 'id':'20ef5475-9f38-4e4c-bd33-de6d979498ec', [x: string]: any }, + 'eaccdc08-ddef-43fe-908f-d108faad57f5': {'message':'You cannot react to Renote.', 'code':'CANNOT_REACT_TO_RENOTE', 'id':'eaccdc08-ddef-43fe-908f-d108faad57f5', [x: string]: any }, '764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37', [x: string]: any }, '92f4426d-4196-4125-aa5b-02943e2ec8fc': {'message':'You are not reacting to that note.', 'code':'NOT_REACTED', 'id':'92f4426d-4196-4125-aa5b-02943e2ec8fc', [x: string]: any }, '12908022-2e21-46cd-ba6a-3edaf6093f46': {'message':'No such note.', 'code':'NO_SUCH_NOTE', 'id':'12908022-2e21-46cd-ba6a-3edaf6093f46', [x: string]: any }, From 88ed25c51482c5276785a137c7b4b617580e9c67 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 14:34:31 +0900 Subject: [PATCH 12/20] fix --- packages/frontend/src/components/MkAutocomplete.vue | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index 6932927172..c5ec468988 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -207,10 +207,6 @@ function exec() { fetching.value = false; // キャッシュ sessionStorage.setItem(cacheKey, JSON.stringify(searchedUsers)); - }).catch((err) => { - if (isAPIError(err)) { - console.error(err); - } }); } } else if (props.type === 'hashtag') { From 3156b2d2b5a1557ed55c01eb662c203bde05c091 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 14:34:47 +0900 Subject: [PATCH 13/20] fix --- packages/frontend/src/components/MkAutocomplete.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index c5ec468988..932c4ecb2e 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -58,7 +58,6 @@ import { miLocalStorage } from '@/local-storage.js'; import { customEmojis } from '@/custom-emojis.js'; import { MFM_TAGS, MFM_PARAMS } from '@/const.js'; import { searchEmoji, EmojiDef } from '@/scripts/search-emoji.js'; -import { isAPIError } from 'misskey-js/api.js'; const lib = emojilist.filter(x => x.category !== 'flags'); From 28af53e2215b9b03ebf35c157fa30e3dd4f9c8d5 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 12 Oct 2024 11:52:42 +0900 Subject: [PATCH 14/20] Merge branch 'develop' into feat-mijs-expose-error-types --- .config/cypress-devcontainer.yml | 224 + .config/docker_example.env | 6 + .config/docker_example.yml | 11 + .config/example.yml | 24 + .../{docker-compose.yml => compose.yml} | 2 - .devcontainer/devcontainer.json | 4 +- .devcontainer/devcontainer.yml | 8 + .devcontainer/init.sh | 3 + .dockerignore | 5 +- .github/ISSUE_TEMPLATE/01_bug-report.yml | 8 +- .github/misskey/test.yml | 2 + .github/workflows/api-misskey-js.yml | 5 +- .github/workflows/changelog-check.yml | 2 +- .../workflows/check-misskey-js-autogen.yml | 10 +- .../workflows/check-misskey-js-version.yml | 3 +- .github/workflows/check-spdx-license-id.yml | 4 + .github/workflows/dockle.yml | 2 +- .github/workflows/get-api-diff.yml | 5 +- .github/workflows/lint.yml | 39 +- .github/workflows/locale.yml | 5 +- .github/workflows/on-release-created.yml | 4 +- .github/workflows/release-edit-with-push.yml | 17 +- .github/workflows/release-with-dispatch.yml | 34 +- .github/workflows/release-with-ready.yml | 15 +- .github/workflows/report-api-diff.yml | 31 +- .github/workflows/storybook.yml | 7 +- .github/workflows/test-backend.yml | 11 +- .github/workflows/test-frontend.yml | 12 +- .github/workflows/test-misskey-js.yml | 7 +- .github/workflows/test-production.yml | 4 +- .github/workflows/validate-api-json.yml | 7 +- .gitignore | 11 +- .gitmodules | 3 - .node-version | 2 +- CHANGELOG.md | 244 +- CONTRIBUTING.md | 128 +- Dockerfile | 4 +- chart/files/default.yml | 8 + ...mpose.local-db.yml => compose.local-db.yml | 2 - ...compose_example.yml => compose_example.yml | 4 +- cypress/e2e/basic.cy.ts | 17 +- cypress/support/commands.ts | 7 +- .../MkAbuseReport.stories.impl.ts | 4 +- idea/MkDisableSection.vue | 41 + idea/README.md | 1 + locales/ar-SA.yml | 11 +- locales/bn-BD.yml | 12 +- locales/ca-ES.yml | 372 +- locales/cs-CZ.yml | 13 +- locales/de-DE.yml | 13 +- locales/el-GR.yml | 3 +- locales/en-US.yml | 165 +- locales/es-ES.yml | 29 +- locales/fr-FR.yml | 17 +- locales/hu-HU.yml | 1 + locales/id-ID.yml | 25 +- locales/index.d.ts | 447 +- locales/index.js | 6 +- locales/it-IT.yml | 168 +- locales/ja-JP.yml | 120 +- locales/ja-KS.yml | 71 +- locales/kab-KAB.yml | 4 + locales/kn-IN.yml | 2 + locales/ko-GS.yml | 26 +- locales/ko-KR.yml | 227 +- locales/lo-LA.yml | 197 +- locales/nl-NL.yml | 1 + locales/no-NO.yml | 5 + locales/pl-PL.yml | 13 +- locales/pt-PT.yml | 1282 +- locales/ro-RO.yml | 9 +- locales/ru-RU.yml | 235 +- locales/si-LK.yml | 3 + locales/sk-SK.yml | 12 +- locales/sv-SE.yml | 6 +- locales/th-TH.yml | 590 +- locales/tr-TR.yml | 1 + locales/ug-CN.yml | 3 + locales/uk-UA.yml | 12 +- locales/uz-UZ.yml | 9 +- locales/vi-VN.yml | 16 +- locales/zh-CN.yml | 191 +- locales/zh-TW.yml | 143 +- misskey-assets | 1 - package.json | 35 +- packages/backend/.eslintignore | 4 - packages/backend/.eslintrc.cjs | 32 - packages/backend/assets/api-doc.html | 20 + packages/backend/assets/embed.js | 31 + packages/backend/assets/redoc.html | 24 - .../backend/assets/tabler-badges/login-2.png | Bin 0 -> 3770 bytes packages/backend/eslint.config.js | 46 + .../1716197366117-MediaSilenceForHosts.js | 16 + .../migration/1721666053703-fixDriveUrl.js | 24 + .../1723944246767-followedMessage.js | 16 + .../1726804538569-reactions-buffering.js | 16 + .../migration/1727491883993-user-score.js | 16 + .../1727512908322-meta-federation.js | 18 + .../1728085812127-refine-abuse-user-report.js | 18 + .../migration/1728550878802-testcaptcha.js | 16 + packages/backend/package.json | 143 +- packages/backend/scripts/dev.mjs | 2 + packages/backend/scripts/generate_api_json.js | 35 +- packages/backend/src/GlobalModule.ts | 73 +- packages/backend/src/config.ts | 53 +- packages/backend/src/const.ts | 2 + .../core/AbuseReportNotificationService.ts | 48 +- .../backend/src/core/AbuseReportService.ts | 84 +- .../backend/src/core/AccountMoveService.ts | 9 +- packages/backend/src/core/AntennaService.ts | 13 +- .../src/core/AvatarDecorationService.ts | 2 +- packages/backend/src/core/CacheService.ts | 12 +- packages/backend/src/core/CaptchaService.ts | 13 + packages/backend/src/core/CoreModule.ts | 29 + .../backend/src/core/CustomEmojiService.ts | 41 +- .../backend/src/core/DeleteAccountService.ts | 62 +- packages/backend/src/core/DownloadService.ts | 2 +- packages/backend/src/core/DriveService.ts | 62 +- packages/backend/src/core/EmailService.ts | 64 +- .../src/core/FederatedInstanceService.ts | 1 + packages/backend/src/core/FileInfoService.ts | 6 +- packages/backend/src/core/FlashService.ts | 40 + .../backend/src/core/GlobalEventService.ts | 30 +- packages/backend/src/core/HashtagService.ts | 12 +- packages/backend/src/core/MetaService.ts | 4 +- packages/backend/src/core/MfmService.ts | 52 +- .../backend/src/core/ModerationLogService.ts | 3 +- .../backend/src/core/NoteCreateService.ts | 95 +- .../backend/src/core/NoteDeleteService.ts | 17 +- .../backend/src/core/ProxyAccountService.ts | 13 +- .../src/core/PushNotificationService.ts | 16 +- packages/backend/src/core/QueueService.ts | 35 +- packages/backend/src/core/ReactionService.ts | 96 +- .../src/core/ReactionsBufferingService.ts | 211 + packages/backend/src/core/RelayService.ts | 2 +- packages/backend/src/core/ReversiService.ts | 33 +- packages/backend/src/core/RoleService.ts | 114 +- packages/backend/src/core/SignupService.ts | 15 +- .../backend/src/core/SystemWebhookService.ts | 13 +- .../backend/src/core/UserFollowingService.ts | 33 +- .../backend/src/core/UserKeypairService.ts | 2 +- .../src/core/UserRenoteMutingService.ts | 52 + .../backend/src/core/UserSearchService.ts | 205 + packages/backend/src/core/UserService.ts | 24 +- .../backend/src/core/UserSuspendService.ts | 79 +- .../backend/src/core/UserWebhookService.ts | 29 +- packages/backend/src/core/UtilityService.ts | 25 + packages/backend/src/core/WebAuthnService.ts | 110 +- .../backend/src/core/WebhookTestService.ts | 451 + .../core/activitypub/ApDbResolverService.ts | 4 +- .../src/core/activitypub/ApInboxService.ts | 12 +- .../src/core/activitypub/ApMfmService.ts | 2 +- .../src/core/activitypub/ApRendererService.ts | 1 + .../src/core/activitypub/ApRequestService.ts | 55 +- .../src/core/activitypub/ApResolverService.ts | 14 +- .../src/core/activitypub/misc/contexts.ts | 1 + .../core/activitypub/models/ApImageService.ts | 11 +- .../core/activitypub/models/ApNoteService.ts | 18 +- .../activitypub/models/ApPersonService.ts | 74 +- .../activitypub/models/ApQuestionService.ts | 4 +- packages/backend/src/core/activitypub/type.ts | 39 +- .../src/core/chart/charts/federation.ts | 19 +- .../entities/AbuseUserReportEntityService.ts | 2 + .../src/core/entities/FlashEntityService.ts | 42 +- .../core/entities/InstanceEntityService.ts | 18 +- .../src/core/entities/MetaEntityService.ts | 33 +- .../src/core/entities/NoteEntityService.ts | 66 +- .../entities/NotificationEntityService.ts | 11 +- .../src/core/entities/UserEntityService.ts | 33 +- .../backend/src/daemons/ServerStatsService.ts | 10 +- packages/backend/src/decorators.ts | 21 +- packages/backend/src/di-symbols.ts | 2 + packages/backend/src/misc/cache.ts | 137 +- packages/backend/src/misc/collapsed-queue.ts | 44 + .../backend/src/misc/fastify-hook-handlers.ts | 2 +- packages/backend/src/misc/is-user-related.ts | 4 + packages/backend/src/misc/json-schema.ts | 9 + packages/backend/src/misc/json-value.ts | 12 + .../backend/src/models/AbuseUserReport.ts | 18 + packages/backend/src/models/DriveFile.ts | 6 +- packages/backend/src/models/Flash.ts | 5 +- packages/backend/src/models/Meta.ts | 28 + packages/backend/src/models/Notification.ts | 15 +- packages/backend/src/models/SystemWebhook.ts | 2 + packages/backend/src/models/User.ts | 6 + packages/backend/src/models/UserProfile.ts | 8 + packages/backend/src/models/Webhook.ts | 1 + .../src/models/json-schema/drive-file.ts | 2 +- .../models/json-schema/federation-instance.ts | 4 + .../backend/src/models/json-schema/flash.ts | 5 + .../backend/src/models/json-schema/meta.ts | 14 + .../backend/src/models/json-schema/note.ts | 1 + .../src/models/json-schema/notification.ts | 42 +- .../backend/src/models/json-schema/role.ts | 24 + .../backend/src/models/json-schema/user.ts | 50 +- .../backend/src/queue/QueueProcessorModule.ts | 5 + .../src/queue/QueueProcessorService.ts | 92 +- .../BakeBufferedReactionsProcessorService.ts | 42 + ...CheckModeratorsActivityProcessorService.ts | 127 + .../processors/DeliverProcessorService.ts | 17 +- .../EndedPollNotificationProcessorService.ts | 11 +- .../ExportAntennasProcessorService.ts | 7 + .../ExportBlockingProcessorService.ts | 7 + .../processors/ExportClipsProcessorService.ts | 7 + .../ExportCustomEmojisProcessorService.ts | 8 + .../ExportFavoritesProcessorService.ts | 7 + .../ExportFollowingProcessorService.ts | 7 + .../ExportMutingProcessorService.ts | 7 + .../processors/ExportNotesProcessorService.ts | 7 + .../ExportUserListsProcessorService.ts | 7 + .../ImportCustomEmojisProcessorService.ts | 41 +- .../queue/processors/InboxProcessorService.ts | 67 +- .../backend/src/server/FileServerService.ts | 10 +- .../backend/src/server/HealthServerService.ts | 4 + .../src/server/NodeinfoServerService.ts | 2 +- packages/backend/src/server/ServerModule.ts | 2 + packages/backend/src/server/ServerService.ts | 11 +- .../backend/src/server/api/ApiCallService.ts | 41 +- .../src/server/api/ApiServerService.ts | 29 +- .../src/server/api/AuthenticateService.ts | 2 +- .../backend/src/server/api/EndpointsModule.ts | 16 + .../src/server/api/SigninApiService.ts | 100 +- .../backend/src/server/api/SigninService.ts | 26 +- .../server/api/SigninWithPasskeyApiService.ts | 173 + .../src/server/api/SignupApiService.ts | 42 +- packages/backend/src/server/api/endpoints.ts | 8 + .../api/endpoints/admin/abuse-user-reports.ts | 16 +- .../api/endpoints/admin/accounts/create.ts | 38 +- .../api/endpoints/admin/accounts/delete.ts | 23 +- .../api/endpoints/admin/announcements/list.ts | 9 +- .../api/endpoints/admin/drive/show-file.ts | 2 +- .../api/endpoints/admin/emoji/update.ts | 33 +- .../admin/forward-abuse-user-report.ts | 55 + .../src/server/api/endpoints/admin/meta.ts | 35 + .../endpoints/admin/queue/deliver-delayed.ts | 19 +- .../endpoints/admin/queue/inbox-delayed.ts | 19 +- .../admin/resolve-abuse-user-report.ts | 4 +- .../admin/roles/update-default-policies.ts | 15 +- .../server/api/endpoints/admin/show-user.ts | 5 + .../server/api/endpoints/admin/show-users.ts | 4 +- .../api/endpoints/admin/suspend-user.ts | 50 +- .../endpoints/admin/system-webhook/test.ts | 77 + .../api/endpoints/admin/unsuspend-user.ts | 14 +- .../admin/update-abuse-user-report.ts | 58 + .../server/api/endpoints/admin/update-meta.ts | 43 + .../server/api/endpoints/antennas/create.ts | 8 +- .../server/api/endpoints/antennas/update.ts | 8 +- .../src/server/api/endpoints/ap/show.ts | 8 +- .../server/api/endpoints/channels/timeline.ts | 13 +- .../backend/src/server/api/endpoints/drive.ts | 5 - .../endpoints/drive/files/attached-notes.ts | 4 +- .../api/endpoints/drive/files/create.ts | 15 +- .../api/endpoints/federation/instances.ts | 2 +- .../server/api/endpoints/federation/stats.ts | 4 +- .../src/server/api/endpoints/flash/delete.ts | 24 +- .../server/api/endpoints/flash/featured.ts | 22 +- .../api/endpoints/gallery/posts/delete.ts | 35 +- .../server/api/endpoints/i/import-antennas.ts | 1 + .../server/api/endpoints/i/import-blocking.ts | 1 + .../api/endpoints/i/import-following.ts | 1 + .../server/api/endpoints/i/import-muting.ts | 1 + .../api/endpoints/i/import-user-lists.ts | 1 + .../server/api/endpoints/i/update-email.ts | 9 +- .../src/server/api/endpoints/i/update.ts | 37 +- .../server/api/endpoints/i/webhooks/create.ts | 1 + .../server/api/endpoints/i/webhooks/list.ts | 1 + .../server/api/endpoints/i/webhooks/show.ts | 1 + .../server/api/endpoints/i/webhooks/test.ts | 76 + .../src/server/api/endpoints/notes/create.ts | 2 - .../api/endpoints/notes/hybrid-timeline.ts | 27 +- .../api/endpoints/notes/local-timeline.ts | 15 +- .../server/api/endpoints/notes/timeline.ts | 15 +- .../server/api/endpoints/notes/translate.ts | 17 +- .../api/endpoints/notes/user-list-timeline.ts | 15 +- .../src/server/api/endpoints/pages/delete.ts | 24 +- .../src/server/api/endpoints/pinned-users.ts | 11 +- .../api/endpoints/renote-mute/create.ts | 23 +- .../api/endpoints/renote-mute/delete.ts | 8 +- .../src/server/api/endpoints/server-info.ts | 10 +- .../src/server/api/endpoints/sw/register.ts | 13 +- .../api/endpoints/username/available.ts | 11 +- .../server/api/endpoints/users/followers.ts | 34 +- .../server/api/endpoints/users/following.ts | 34 +- .../src/server/api/endpoints/users/notes.ts | 11 +- .../server/api/endpoints/users/reactions.ts | 19 +- .../users/search-by-username-and-host.ts | 101 +- .../src/server/api/endpoints/users/search.ts | 126 +- .../api/openapi/OpenApiServerService.ts | 2 +- .../src/server/api/openapi/gen-spec.ts | 1 - .../src/server/api/stream/Connection.ts | 68 +- .../backend/src/server/api/stream/channel.ts | 13 +- .../src/server/api/stream/channels/admin.ts | 3 +- .../src/server/api/stream/channels/antenna.ts | 6 +- .../src/server/api/stream/channels/channel.ts | 6 +- .../src/server/api/stream/channels/drive.ts | 3 +- .../api/stream/channels/global-timeline.ts | 7 +- .../src/server/api/stream/channels/hashtag.ts | 7 +- .../api/stream/channels/home-timeline.ts | 11 +- .../api/stream/channels/hybrid-timeline.ts | 21 +- .../api/stream/channels/local-timeline.ts | 9 +- .../src/server/api/stream/channels/main.ts | 3 +- .../server/api/stream/channels/queue-stats.ts | 11 +- .../api/stream/channels/reversi-game.ts | 36 +- .../src/server/api/stream/channels/reversi.ts | 3 +- .../api/stream/channels/role-timeline.ts | 6 +- .../api/stream/channels/server-stats.ts | 9 +- .../server/api/stream/channels/user-list.ts | 10 +- .../src/server/web/ClientServerService.ts | 180 +- .../src/server/web/UrlPreviewService.ts | 17 +- packages/backend/src/server/web/boot.embed.js | 219 + packages/backend/src/server/web/boot.js | 33 +- packages/backend/src/server/web/style.css | 9 +- .../backend/src/server/web/style.embed.css | 99 + .../src/server/web/views/base-embed.pug | 72 + .../backend/src/server/web/views/base.pug | 15 +- packages/backend/src/types.ts | 60 +- packages/backend/test-server/.eslintrc.cjs | 32 - packages/backend/test-server/entry.ts | 22 +- packages/backend/test-server/eslint.config.js | 43 + packages/backend/test/.eslintrc.cjs | 11 - .../test/{docker-compose.yml => compose.yml} | 2 - packages/backend/test/e2e/2fa.ts | 106 +- packages/backend/test/e2e/antennas.ts | 23 + packages/backend/test/e2e/api-visibility.ts | 16 +- packages/backend/test/e2e/block.ts | 12 +- packages/backend/test/e2e/clips.ts | 12 +- packages/backend/test/e2e/drive.ts | 6 +- packages/backend/test/e2e/endpoints.ts | 40 +- packages/backend/test/e2e/exports.ts | 70 +- packages/backend/test/e2e/move.ts | 73 +- packages/backend/test/e2e/mute.ts | 72 +- packages/backend/test/e2e/note.ts | 79 +- packages/backend/test/e2e/renote-mute.ts | 25 +- packages/backend/test/e2e/streaming.ts | 62 + .../backend/test/e2e/synalio/abuse-report.ts | 67 +- .../backend/test/e2e/synalio/user-create.ts | 130 + packages/backend/test/e2e/thread-mute.ts | 10 +- packages/backend/test/e2e/timelines.ts | 498 +- packages/backend/test/e2e/user-notes.ts | 4 +- packages/backend/test/e2e/users.ts | 35 +- packages/backend/test/eslint.config.js | 22 + packages/backend/test/jest.setup.ts | 6 +- packages/backend/test/misc/mock-resolver.ts | 3 +- packages/backend/test/resources/192.jpg | Bin 0 -> 5131 bytes packages/backend/test/resources/192.png | Bin 0 -> 26568 bytes packages/backend/test/resources/Lenna.jpg | Bin 25360 -> 0 bytes packages/backend/test/resources/Lenna.png | Bin 473831 -> 0 bytes .../unit/AbuseReportNotificationService.ts | 6 +- packages/backend/test/unit/ApMfmService.ts | 8 +- packages/backend/test/unit/FileInfoService.ts | 111 +- packages/backend/test/unit/FlashService.ts | 152 + packages/backend/test/unit/RoleService.ts | 203 +- .../test/unit/SigninWithPasskeyApiService.ts | 182 + .../backend/test/unit/SystemWebhookService.ts | 26 +- .../backend/test/unit/UserSearchService.ts | 265 + .../backend/test/unit/UserWebhookService.ts | 245 + .../backend/test/unit/WebhookTestService.ts | 225 + packages/backend/test/unit/activitypub.ts | 74 +- .../test/unit/entities/UserEntityService.ts | 4 +- ...CheckModeratorsActivityProcessorService.ts | 235 + packages/backend/test/utils.ts | 95 +- packages/frontend-embed/.gitignore | 1 + packages/frontend-embed/@types/global.d.ts | 23 + packages/frontend-embed/@types/theme.d.ts | 12 + packages/frontend-embed/assets/dummy.png | Bin 0 -> 6285 bytes packages/frontend-embed/eslint.config.js | 95 + packages/frontend-embed/package.json | 72 + packages/frontend-embed/src/boot.ts | 141 + .../frontend-embed/src/components/EmA.vue | 21 + .../frontend-embed/src/components/EmAcct.vue | 24 + .../src/components/EmAvatar.vue | 250 + .../src/components/EmCustomEmoji.vue | 99 + .../frontend-embed/src/components/EmEmoji.vue | 26 + .../frontend-embed/src/components/EmError.vue | 43 + .../src/components/EmImgWithBlurhash.vue | 240 + .../src/components/EmInstanceTicker.vue | 87 + .../frontend-embed/src/components/EmLink.vue | 40 + .../src/components/EmLoading.vue | 112 + .../src/components/EmMediaBanner.vue | 55 + .../src/components/EmMediaImage.vue | 162 + .../src/components/EmMediaList.vue | 146 + .../src/components/EmMediaVideo.vue | 64 + .../src/components/EmMention.vue | 46 + .../frontend-embed/src/components/EmMfm.ts | 454 + .../frontend-embed/src/components/EmNote.vue | 611 + .../src/components/EmNoteDetailed.vue | 490 + .../src/components/EmNoteHeader.vue | 104 + .../src/components/EmNoteSimple.vue | 106 + .../src/components/EmNoteSub.vue | 151 + .../frontend-embed/src/components/EmNotes.vue | 52 + .../src/components/EmPagination.vue | 504 + .../frontend-embed/src/components/EmPoll.vue | 82 + .../src/components/EmReactionIcon.vue | 23 + .../components/EmReactionsViewer.reaction.vue | 99 + .../src/components/EmReactionsViewer.vue | 104 + .../src/components/EmSubNoteContent.vue | 114 + .../frontend-embed/src/components/EmTime.vue | 107 + .../src/components/EmTimelineContainer.vue | 39 + .../frontend-embed/src/components/EmUrl.vue | 96 + .../src/components/EmUserName.vue | 21 + .../frontend-embed/src/components/I18n.vue | 51 + packages/frontend-embed/src/custom-emojis.ts | 61 + packages/frontend-embed/src/di.ts | 17 + packages/frontend-embed/src/i18n.ts | 15 + packages/frontend-embed/src/index.html | 36 + packages/frontend-embed/src/misskey-api.ts | 99 + packages/frontend-embed/src/pages/clip.vue | 143 + .../frontend-embed/src/pages/not-found.vue | 24 + packages/frontend-embed/src/pages/note.vue | 52 + packages/frontend-embed/src/pages/tag.vue | 126 + .../src/pages/user-timeline.vue | 158 + packages/frontend-embed/src/post-message.ts | 49 + packages/frontend-embed/src/server-context.ts | 21 + .../frontend-embed/src/server-metadata.ts | 16 + packages/frontend-embed/src/style.scss | 453 + packages/frontend-embed/src/theme.ts | 108 + packages/frontend-embed/src/ui.vue | 110 + packages/frontend-embed/src/utils.ts | 23 + .../src/workers/draw-blurhash.ts | 22 + .../frontend-embed/src/workers/test-webgl2.ts | 14 + .../frontend-embed/src/workers/tsconfig.json | 5 + packages/frontend-embed/tsconfig.json | 53 + .../frontend-embed/vite.config.local-dev.ts | 96 + packages/frontend-embed/vite.config.ts | 161 + packages/frontend-embed/vite.json5.ts | 48 + packages/frontend-embed/vue-shims.d.ts | 6 + packages/frontend-shared/.gitignore | 2 + packages/frontend-shared/@types/global.d.ts | 25 + packages/frontend-shared/build.js | 106 + packages/frontend-shared/eslint.config.js | 100 + .../js}/collapsed.ts | 4 +- .../src => frontend-shared/js}/config.ts | 17 +- .../src => frontend-shared/js}/const.ts | 11 +- packages/frontend-shared/js/embed-page.ts | 97 + .../js}/emoji-base.ts | 4 +- .../src => frontend-shared/js}/emojilist.json | 0 .../js}/emojilist.ts | 4 +- .../js}/extract-avg-color-from-blurhash.ts | 0 .../scripts => frontend-shared/js}/i18n.ts | 77 +- packages/frontend-shared/js/intl-const.ts | 51 + packages/frontend-shared/js/is-link.ts | 12 + packages/frontend-shared/js/media-proxy.ts | 63 + .../scripts => frontend-shared/js}/scroll.ts | 31 +- .../src/scripts => frontend-shared/js}/url.ts | 15 +- .../js}/use-document-visibility.ts | 3 +- .../js}/use-interval.ts | 0 .../js}/worker-multi-dispatch.ts | 12 +- packages/frontend-shared/package.json | 39 + .../themes/_dark.json5 | 20 +- .../themes/_light.json5 | 20 +- .../themes/d-astro.json5 | 12 +- .../themes/d-botanical.json5 | 0 .../themes/d-cherry.json5 | 0 .../themes/d-dark.json5 | 0 .../themes/d-future.json5 | 0 .../themes/d-green-lime.json5 | 0 .../themes/d-green-orange.json5 | 0 .../themes/d-ice.json5 | 0 .../themes/d-persimmon.json5 | 0 .../src => frontend-shared}/themes/d-u0.json5 | 8 +- .../themes/l-apricot.json5 | 0 .../themes/l-botanical.json5 | 0 .../themes/l-cherry.json5 | 0 .../themes/l-coffee.json5 | 0 .../themes/l-light.json5 | 0 .../themes/l-rainy.json5 | 0 .../themes/l-sushi.json5 | 0 .../src => frontend-shared}/themes/l-u0.json5 | 6 +- .../themes/l-vivid.json5 | 13 +- packages/frontend-shared/tsconfig.json | 41 + packages/frontend/.eslintrc.cjs | 82 - packages/frontend/.storybook/changes.ts | 2 - packages/frontend/.storybook/fakes.ts | 87 +- packages/frontend/.storybook/generate.tsx | 17 +- packages/frontend/.storybook/preload-theme.ts | 2 +- packages/frontend/.storybook/preview.ts | 6 +- packages/frontend/@types/theme.d.ts | 2 +- packages/frontend/assets/testcaptcha.png | Bin 0 -> 2634 bytes packages/frontend/eslint.config.js | 95 + packages/frontend/package.json | 146 +- packages/frontend/src/_boot_.ts | 2 + packages/frontend/src/_dev_boot_.ts | 7 +- packages/frontend/src/account.ts | 66 +- packages/frontend/src/boot/common.ts | 22 +- packages/frontend/src/boot/main-boot.ts | 137 +- packages/frontend/src/boot/sub-boot.ts | 3 + .../frontend/src/components/MkAbuseReport.vue | 193 +- .../src/components/MkAbuseReportWindow.vue | 2 +- .../src/components/MkAccountMoved.vue | 8 +- .../src/components/MkAchievements.vue | 4 +- .../frontend/src/components/MkAnalogClock.vue | 6 +- .../src/components/MkAnnouncementDialog.vue | 10 +- .../MkAntennaEditor.stories.impl.ts | 62 + .../MkAntennaEditor.vue} | 77 +- .../MkAntennaEditorDialog.stories.impl.ts | 63 + .../src/components/MkAntennaEditorDialog.vue | 63 + packages/frontend/src/components/MkAsUi.vue | 29 +- .../src/components/MkAutocomplete.vue | 12 +- packages/frontend/src/components/MkButton.vue | 26 +- .../frontend/src/components/MkCaptcha.vue | 29 +- .../MkChannelFollowButton.stories.impl.ts | 6 - .../src/components/MkChannelFollowButton.vue | 28 +- .../src/components/MkChannelPreview.vue | 29 +- packages/frontend/src/components/MkChart.vue | 54 +- .../frontend/src/components/MkChartLegend.vue | 4 +- .../components/MkClickerGame.stories.impl.ts | 12 +- .../frontend/src/components/MkClickerGame.vue | 6 +- .../components/MkClipPreview.stories.impl.ts | 1 + .../frontend/src/components/MkClipPreview.vue | 29 +- .../frontend/src/components/MkCode.core.vue | 2 +- packages/frontend/src/components/MkCode.vue | 21 +- .../frontend/src/components/MkCodeEditor.vue | 14 +- .../frontend/src/components/MkCodeInline.vue | 2 +- .../frontend/src/components/MkColorInput.vue | 14 +- .../frontend/src/components/MkContainer.vue | 16 +- .../frontend/src/components/MkContextMenu.vue | 4 +- .../src/components/MkCropperDialog.vue | 8 +- .../MkCustomEmojiDetailedDialog.vue | 10 +- .../src/components/MkCwButton.stories.impl.ts | 10 - .../frontend/src/components/MkCwButton.vue | 4 +- .../MkDateSeparatedList.stories.impl.ts | 7 + .../src/components/MkDateSeparatedList.vue | 25 +- .../src/components/MkDialog.stories.impl.ts | 159 + packages/frontend/src/components/MkDialog.vue | 44 +- .../src/components/MkDivider.stories.impl.ts | 7 + .../frontend/src/components/MkDivider.vue | 2 +- .../src/components/MkDonation.stories.impl.ts | 54 + .../frontend/src/components/MkDonation.vue | 8 +- .../components/MkDrive.file.stories.impl.ts | 48 + .../frontend/src/components/MkDrive.file.vue | 40 +- .../components/MkDrive.folder.stories.impl.ts | 70 + .../src/components/MkDrive.folder.vue | 87 +- .../MkDrive.navFolder.stories.impl.ts | 7 + .../src/components/MkDrive.stories.impl.ts | 82 + packages/frontend/src/components/MkDrive.vue | 42 +- .../MkDriveFileThumbnail.stories.impl.ts | 41 + .../src/components/MkDriveFileThumbnail.vue | 25 +- .../MkDriveSelectDialog.stories.impl.ts | 7 + .../components/MkDriveWindow.stories.impl.ts | 7 + .../src/components/MkEmbedCodeGenDialog.vue | 414 + .../MkEmojiPicker.section.stories.impl.ts | 7 + .../src/components/MkEmojiPicker.section.vue | 6 +- .../components/MkEmojiPicker.stories.impl.ts | 54 + .../frontend/src/components/MkEmojiPicker.vue | 68 +- .../MkEmojiPickerDialog.stories.impl.ts | 7 + .../src/components/MkEmojiPickerDialog.vue | 5 +- .../MkExtensionInstaller.stories.impl.ts | 83 + .../src/components/MkExtensionInstaller.vue | 146 + .../src/components/MkFileListForAdmin.vue | 4 +- .../components/MkFlashPreview.stories.impl.ts | 53 + .../src/components/MkFlashPreview.vue | 19 +- .../src/components/MkFoldableSection.vue | 10 +- packages/frontend/src/components/MkFolder.vue | 64 +- .../src/components/MkFollowButton.vue | 38 +- .../src/components/MkFormDialog.file.vue | 2 +- .../frontend/src/components/MkFormFooter.vue | 49 + .../frontend/src/components/MkFukidashi.vue | 100 + .../src/components/MkGalleryPostPreview.vue | 6 +- packages/frontend/src/components/MkGoogle.vue | 4 +- .../src/components/MkImgWithBlurhash.vue | 18 +- packages/frontend/src/components/MkInfo.vue | 10 +- packages/frontend/src/components/MkInput.vue | 20 +- .../src/components/MkInstanceCardMini.vue | 6 +- .../src/components/MkInstanceStats.vue | 6 +- .../src/components/MkInstanceTicker.vue | 2 +- .../frontend/src/components/MkInviteCode.vue | 23 +- .../frontend/src/components/MkKeyValue.vue | 2 +- .../frontend/src/components/MkLaunchPad.vue | 8 +- packages/frontend/src/components/MkLink.vue | 8 +- .../frontend/src/components/MkMediaAudio.vue | 105 +- .../frontend/src/components/MkMediaBanner.vue | 27 +- .../frontend/src/components/MkMediaImage.vue | 91 +- .../frontend/src/components/MkMediaList.vue | 78 +- .../frontend/src/components/MkMediaRange.vue | 4 +- .../frontend/src/components/MkMediaVideo.vue | 97 +- .../frontend/src/components/MkMention.vue | 17 +- .../frontend/src/components/MkMenu.child.vue | 7 +- packages/frontend/src/components/MkMenu.vue | 490 +- .../frontend/src/components/MkMiniChart.vue | 4 +- packages/frontend/src/components/MkModal.vue | 40 +- .../frontend/src/components/MkModalWindow.vue | 57 +- packages/frontend/src/components/MkNote.vue | 209 +- .../src/components/MkNoteDetailed.vue | 184 +- .../frontend/src/components/MkNoteHeader.vue | 3 +- .../frontend/src/components/MkNotePreview.vue | 2 +- .../frontend/src/components/MkNoteSimple.vue | 2 +- .../frontend/src/components/MkNoteSub.vue | 4 +- packages/frontend/src/components/MkNotes.vue | 8 +- .../src/components/MkNotification.vue | 71 +- .../components/MkNotificationSelectWindow.vue | 2 +- .../src/components/MkNotifications.vue | 4 +- .../frontend/src/components/MkNumberDiff.vue | 4 +- .../src/components/MkObjectView.value.vue | 8 +- packages/frontend/src/components/MkOmit.vue | 8 +- .../frontend/src/components/MkPagePreview.vue | 30 +- .../frontend/src/components/MkPageWindow.vue | 10 +- .../frontend/src/components/MkPagination.vue | 17 +- packages/frontend/src/components/MkPoll.vue | 29 +- .../frontend/src/components/MkPollEditor.vue | 2 +- .../frontend/src/components/MkPopupMenu.vue | 8 +- .../frontend/src/components/MkPostForm.vue | 101 +- .../src/components/MkPostFormAttaches.vue | 50 +- .../src/components/MkPostFormDialog.vue | 2 +- .../frontend/src/components/MkPreview.vue | 150 + .../src/components/MkPullToRefresh.vue | 2 +- packages/frontend/src/components/MkRadio.vue | 28 +- packages/frontend/src/components/MkRadios.vue | 6 +- packages/frontend/src/components/MkRange.vue | 80 +- .../src/components/MkReactionEffect.vue | 2 +- .../src/components/MkReactionIcon.vue | 6 +- .../src/components/MkReactionTooltip.vue | 1 + .../components/MkReactionsViewer.details.vue | 6 +- .../components/MkReactionsViewer.reaction.vue | 26 +- .../src/components/MkRemoteCaution.vue | 8 +- .../src/components/MkRetentionLineChart.vue | 2 +- .../src/components/MkRippleEffect.vue | 4 +- .../frontend/src/components/MkRolePreview.vue | 71 +- packages/frontend/src/components/MkSelect.vue | 45 +- .../src/components/MkSignin.input.vue | 206 + .../src/components/MkSignin.passkey.vue | 92 + .../src/components/MkSignin.password.vue | 188 + .../frontend/src/components/MkSignin.totp.vue | 74 + packages/frontend/src/components/MkSignin.vue | 506 +- .../src/components/MkSigninDialog.vue | 88 +- .../src/components/MkSignupDialog.form.vue | 127 +- .../src/components/MkSignupDialog.rules.vue | 16 +- .../src/components/MkSignupDialog.vue | 4 +- .../components/MkSourceCodeAvailablePopup.vue | 8 +- .../src/components/MkSubNoteContent.vue | 16 +- .../frontend/src/components/MkSuperMenu.vue | 32 +- .../src/components/MkSwitch.button.vue | 12 +- packages/frontend/src/components/MkSwitch.vue | 16 +- .../components/MkSystemWebhookEditor.impl.ts | 16 +- .../src/components/MkSystemWebhookEditor.vue | 163 +- packages/frontend/src/components/MkTab.vue | 8 +- .../frontend/src/components/MkTagCloud.vue | 2 +- .../frontend/src/components/MkTextarea.vue | 14 +- .../frontend/src/components/MkTimeline.vue | 3 +- .../src/components/MkTokenGenerateWindow.vue | 8 +- .../frontend/src/components/MkTooltip.vue | 2 +- .../src/components/MkTutorialDialog.Note.vue | 10 +- .../components/MkTutorialDialog.PostNote.vue | 14 +- .../components/MkTutorialDialog.Sensitive.vue | 16 +- .../components/MkTutorialDialog.Timeline.vue | 23 +- .../src/components/MkTutorialDialog.vue | 10 +- .../frontend/src/components/MkUpdated.vue | 6 +- .../frontend/src/components/MkUrlPreview.vue | 22 +- .../MkUserAnnouncementEditDialog.vue | 12 +- .../src/components/MkUserCardMini.vue | 6 +- .../frontend/src/components/MkUserInfo.vue | 18 +- .../frontend/src/components/MkUserList.vue | 2 +- .../src/components/MkUserOnlineIndicator.vue | 2 +- .../frontend/src/components/MkUserPopup.vue | 13 +- .../src/components/MkUserSelectDialog.vue | 14 +- .../components/MkUserSetupDialog.Follow.vue | 2 +- .../src/components/MkUserSetupDialog.User.vue | 6 +- .../src/components/MkUserSetupDialog.vue | 18 +- .../src/components/MkVisibilityPicker.vue | 4 +- .../MkVisitorDashboard.ActiveUsersChart.vue | 2 +- .../src/components/MkVisitorDashboard.vue | 35 +- .../src/components/MkWaitingDialog.vue | 6 +- .../frontend/src/components/MkWidgets.vue | 12 +- packages/frontend/src/components/MkWindow.vue | 30 +- .../src/components/MkYouTubePlayer.vue | 5 +- .../frontend/src/components/form/link.vue | 10 +- .../frontend/src/components/form/section.vue | 6 +- .../frontend/src/components/form/slot.vue | 2 +- .../src/components/global/MkA.stories.impl.ts | 2 - .../frontend/src/components/global/MkA.vue | 4 +- .../frontend/src/components/global/MkAcct.vue | 10 +- .../components/global/MkAd.stories.impl.ts | 87 +- .../frontend/src/components/global/MkAd.vue | 8 +- .../src/components/global/MkAvatar.vue | 19 +- .../src/components/global/MkCondensedLine.vue | 2 +- .../src/components/global/MkCustomEmoji.vue | 37 +- .../src/components/global/MkEmoji.vue | 33 +- .../src/components/global/MkLoading.vue | 2 +- ....stories.impl.ts => MkMfm.stories.impl.ts} | 17 +- ...{MkMisskeyFlavoredMarkdown.ts => MkMfm.ts} | 37 +- .../components/global/MkPageHeader.tabs.vue | 2 +- .../src/components/global/MkPageHeader.vue | 14 +- .../components/global/MkStickyContainer.vue | 21 +- .../components/global/MkTime.stories.impl.ts | 2 +- .../frontend/src/components/global/MkTime.vue | 6 +- .../frontend/src/components/global/MkUrl.vue | 17 +- .../src/components/global/RouterView.vue | 7 +- packages/frontend/src/components/index.ts | 2 +- .../src/components/page/page.dynamic.vue | 6 +- .../src/components/page/page.image.vue | 4 +- .../src/components/page/page.note.vue | 4 +- packages/frontend/src/custom-emojis.ts | 22 +- .../frontend/src/directives/adaptive-bg.ts | 2 +- .../src/directives/adaptive-border.ts | 2 +- .../frontend/src/directives/follow-append.ts | 2 +- packages/frontend/src/directives/hotkey.ts | 6 +- packages/frontend/src/directives/panel.ts | 6 +- packages/frontend/src/directives/ripple.ts | 4 +- packages/frontend/src/directives/tooltip.ts | 6 +- .../frontend/src/directives/user-preview.ts | 5 +- packages/frontend/src/filters/date.ts | 2 +- packages/frontend/src/filters/number.ts | 2 +- packages/frontend/src/filters/user.ts | 2 +- packages/frontend/src/i18n.ts | 7 +- packages/frontend/src/instance.ts | 2 +- packages/frontend/src/local-storage.ts | 24 +- packages/frontend/src/navbar.ts | 4 +- packages/frontend/src/nirax.ts | 9 +- packages/frontend/src/os.ts | 205 +- packages/frontend/src/pages/_error_.vue | 2 +- packages/frontend/src/pages/about-misskey.vue | 50 +- .../frontend/src/pages/about.federation.vue | 8 +- .../frontend/src/pages/about.overview.vue | 205 + packages/frontend/src/pages/about.vue | 201 +- packages/frontend/src/pages/admin-file.vue | 10 +- packages/frontend/src/pages/admin-user.vue | 37 +- .../src/pages/admin/RolesEditorFormula.vue | 6 +- .../frontend/src/pages/admin/_header_.vue | 17 +- .../notification-recipient.editor.vue | 60 +- .../notification-recipient.item.vue | 4 +- .../abuse-report/notification-recipient.vue | 15 +- packages/frontend/src/pages/admin/abuses.vue | 19 +- packages/frontend/src/pages/admin/ads.vue | 10 +- .../src/pages/admin/announcements.vue | 162 +- .../src/pages/admin/bot-protection.vue | 257 +- .../frontend/src/pages/admin/branding.vue | 6 +- .../src/pages/admin/email-settings.vue | 4 +- .../src/pages/admin/external-services.vue | 23 +- .../frontend/src/pages/admin/federation.vue | 8 +- packages/frontend/src/pages/admin/files.vue | 4 +- packages/frontend/src/pages/admin/index.vue | 53 +- .../src/pages/admin/instance-block.vue | 73 - packages/frontend/src/pages/admin/invites.vue | 2 +- .../frontend/src/pages/admin/moderation.vue | 210 +- .../src/pages/admin/modlog.ModLog.vue | 26 +- packages/frontend/src/pages/admin/modlog.vue | 11 +- .../src/pages/admin/object-storage.vue | 4 +- .../src/pages/admin/other-settings.vue | 93 - .../overview.ap-requests.stories.impl.ts | 41 + .../src/pages/admin/overview.ap-requests.vue | 15 +- .../src/pages/admin/overview.federation.vue | 4 +- .../src/pages/admin/overview.instances.vue | 2 +- .../frontend/src/pages/admin/overview.pie.vue | 2 +- .../src/pages/admin/overview.queue.vue | 24 +- .../src/pages/admin/overview.stats.vue | 4 +- .../src/pages/admin/overview.users.vue | 10 +- .../frontend/src/pages/admin/performance.vue | 193 + .../src/pages/admin/proxy-account.vue | 71 - .../frontend/src/pages/admin/queue.chart.vue | 34 +- packages/frontend/src/pages/admin/queue.vue | 8 +- packages/frontend/src/pages/admin/relays.vue | 4 +- .../frontend/src/pages/admin/roles.edit.vue | 4 +- .../frontend/src/pages/admin/roles.editor.vue | 122 +- .../frontend/src/pages/admin/roles.role.vue | 2 +- packages/frontend/src/pages/admin/roles.vue | 53 +- .../frontend/src/pages/admin/security.vue | 321 +- .../frontend/src/pages/admin/server-rules.vue | 10 +- .../frontend/src/pages/admin/settings.vue | 533 +- .../src/pages/admin/system-webhook.item.vue | 103 +- .../src/pages/admin/system-webhook.vue | 9 +- packages/frontend/src/pages/admin/users.vue | 4 +- packages/frontend/src/pages/announcement.vue | 6 +- packages/frontend/src/pages/announcements.vue | 6 +- .../frontend/src/pages/antenna-timeline.vue | 17 +- .../frontend/src/pages/avatar-decorations.vue | 93 +- .../frontend/src/pages/channel-editor.vue | 2 +- packages/frontend/src/pages/channel.vue | 18 +- packages/frontend/src/pages/clip.vue | 52 +- packages/frontend/src/pages/contact.vue | 26 +- .../src/pages/custom-emojis-manager.vue | 28 +- .../frontend/src/pages/drive.file.info.vue | 75 +- .../src/pages/drop-and-fusion.game.vue | 22 +- .../frontend/src/pages/emoji-edit-dialog.vue | 12 +- packages/frontend/src/pages/emojis.emoji.vue | 14 +- .../frontend/src/pages/explore.featured.vue | 2 +- packages/frontend/src/pages/explore.users.vue | 2 +- packages/frontend/src/pages/favorites.vue | 4 +- .../frontend/src/pages/flash/flash-edit.vue | 48 +- .../frontend/src/pages/flash/flash-index.vue | 3 +- packages/frontend/src/pages/flash/flash.vue | 85 +- packages/frontend/src/pages/follow.vue | 71 - packages/frontend/src/pages/gallery/edit.vue | 4 +- packages/frontend/src/pages/gallery/index.vue | 2 +- packages/frontend/src/pages/gallery/post.vue | 77 +- packages/frontend/src/pages/games.vue | 11 +- .../frontend/src/pages/install-extensions.vue | 125 +- packages/frontend/src/pages/instance-info.vue | 41 +- packages/frontend/src/pages/list.vue | 2 +- packages/frontend/src/pages/lookup.vue | 97 + .../frontend/src/pages/my-antennas/create.vue | 32 +- .../frontend/src/pages/my-antennas/edit.vue | 17 +- .../frontend/src/pages/my-antennas/index.vue | 4 +- .../frontend/src/pages/my-clips/index.vue | 2 +- .../frontend/src/pages/my-lists/index.vue | 4 +- packages/frontend/src/pages/my-lists/list.vue | 41 +- packages/frontend/src/pages/note.vue | 8 +- packages/frontend/src/pages/notifications.vue | 4 +- .../frontend/src/pages/page-editor/common.ts | 15 + .../els/page-editor.el.section.vue | 5 +- .../page-editor/els/page-editor.el.text.vue | 2 +- .../page-editor/page-editor.container.vue | 6 +- .../src/pages/page-editor/page-editor.vue | 13 +- packages/frontend/src/pages/page.vue | 148 +- packages/frontend/src/pages/preview.vue | 26 + .../frontend/src/pages/reset-password.vue | 4 +- .../frontend/src/pages/reversi/game.board.vue | 20 +- .../src/pages/reversi/game.setting.vue | 18 +- packages/frontend/src/pages/reversi/game.vue | 4 +- packages/frontend/src/pages/reversi/index.vue | 22 +- packages/frontend/src/pages/role.vue | 2 +- packages/frontend/src/pages/scratchpad.vue | 79 +- packages/frontend/src/pages/search.note.vue | 204 +- .../frontend/src/pages/search.stories.impl.ts | 88 + packages/frontend/src/pages/search.user.vue | 72 +- packages/frontend/src/pages/search.vue | 34 +- packages/frontend/src/pages/settings/2fa.vue | 8 +- .../frontend/src/pages/settings/accounts.vue | 28 +- packages/frontend/src/pages/settings/api.vue | 5 +- packages/frontend/src/pages/settings/apps.vue | 73 +- .../settings/avatar-decoration.decoration.vue | 6 +- .../settings/avatar-decoration.dialog.vue | 7 +- .../src/pages/settings/avatar-decoration.vue | 7 +- .../src/pages/settings/drive-cleaner.vue | 8 +- .../frontend/src/pages/settings/drive.vue | 2 +- .../frontend/src/pages/settings/email.vue | 2 +- .../src/pages/settings/emoji-picker.vue | 21 +- .../frontend/src/pages/settings/general.vue | 51 +- .../src/pages/settings/import-export.vue | 10 +- .../frontend/src/pages/settings/index.vue | 5 +- .../src/pages/settings/mute-block.vue | 2 +- .../frontend/src/pages/settings/navbar.vue | 18 +- .../src/pages/settings/notifications.vue | 4 +- .../frontend/src/pages/settings/other.vue | 24 +- .../frontend/src/pages/settings/plugin.vue | 2 +- .../pages/settings/preferences-backups.vue | 72 +- .../frontend/src/pages/settings/profile.vue | 69 +- .../frontend/src/pages/settings/security.vue | 6 +- .../src/pages/settings/sounds.sound.vue | 46 +- .../frontend/src/pages/settings/sounds.vue | 12 +- .../pages/settings/statusbar.statusbar.vue | 4 +- .../src/pages/settings/theme.manage.vue | 2 +- .../frontend/src/pages/settings/theme.vue | 34 +- .../src/pages/settings/webhook.edit.vue | 90 +- .../src/pages/settings/webhook.new.vue | 2 +- .../frontend/src/pages/settings/webhook.vue | 4 +- .../frontend/src/pages/signup-complete.vue | 6 +- packages/frontend/src/pages/tag.vue | 23 +- packages/frontend/src/pages/theme-editor.vue | 8 +- packages/frontend/src/pages/timeline.vue | 139 +- .../frontend/src/pages/user-list-timeline.vue | 12 +- packages/frontend/src/pages/user/clips.vue | 2 +- .../frontend/src/pages/user/follow-list.vue | 2 +- packages/frontend/src/pages/user/gallery.vue | 2 +- packages/frontend/src/pages/user/home.vue | 87 +- .../src/pages/user/index.timeline.vue | 8 +- packages/frontend/src/pages/user/lists.vue | 4 +- packages/frontend/src/pages/user/raw.vue | 12 +- .../frontend/src/pages/user/reactions.vue | 2 +- .../frontend/src/pages/welcome.entrance.a.vue | 12 +- packages/frontend/src/pages/welcome.setup.vue | 34 +- .../src/pages/welcome.timeline.note.vue | 109 + .../frontend/src/pages/welcome.timeline.vue | 100 +- packages/frontend/src/pages/welcome.vue | 2 +- packages/frontend/src/router/definition.ts | 69 +- packages/frontend/src/router/main.ts | 29 +- packages/frontend/src/scripts/aiscript/api.ts | 6 +- packages/frontend/src/scripts/aiscript/ui.ts | 8 + .../frontend/src/scripts/check-permissions.ts | 19 + .../src/scripts/check-reaction-permissions.ts | 2 +- .../frontend/src/scripts/code-highlighter.ts | 8 +- .../frontend/src/scripts/copy-to-clipboard.ts | 31 +- packages/frontend/src/scripts/focus-trap.ts | 134 + packages/frontend/src/scripts/focus.ts | 98 +- .../frontend/src/scripts/gen-search-query.ts | 2 +- .../frontend/src/scripts/get-appear-note.ts | 10 + .../src/scripts/get-dom-node-or-null.ts | 19 + .../src/scripts/get-drive-file-menu.ts | 58 +- .../frontend/src/scripts/get-embed-code.ts | 87 + .../frontend/src/scripts/get-note-menu.ts | 425 +- .../frontend/src/scripts/get-user-menu.ts | 308 +- packages/frontend/src/scripts/hotkey.ts | 205 +- packages/frontend/src/scripts/idb-proxy.ts | 11 +- packages/frontend/src/scripts/init-chart.ts | 2 +- .../frontend/src/scripts/initialize-sw.ts | 2 +- .../frontend/src/scripts/install-plugin.ts | 5 +- packages/frontend/src/scripts/intl-const.ts | 2 +- .../frontend/src/scripts/isFfVisibleForMe.ts | 4 +- packages/frontend/src/scripts/keycode.ts | 24 - packages/frontend/src/scripts/lookup.ts | 2 +- packages/frontend/src/scripts/media-proxy.ts | 53 +- packages/frontend/src/scripts/merge.ts | 2 +- .../src/scripts/mfm-function-picker.ts | 31 +- packages/frontend/src/scripts/misskey-api.ts | 2 +- .../src/scripts/player-url-transform.ts | 26 + packages/frontend/src/scripts/please-login.ts | 46 +- packages/frontend/src/scripts/popout.ts | 4 +- packages/frontend/src/scripts/post-message.ts | 2 +- packages/frontend/src/scripts/reload-ask.ts | 40 + packages/frontend/src/scripts/safe-parse.ts | 11 - .../frontend/src/scripts/safe-uri-decode.ts | 12 - packages/frontend/src/scripts/sound.ts | 50 +- packages/frontend/src/scripts/stream-mock.ts | 81 + packages/frontend/src/scripts/test-utils.ts | 10 - packages/frontend/src/scripts/theme.ts | 10 +- packages/frontend/src/scripts/upload.ts | 12 +- .../frontend/src/scripts/use-chart-tooltip.ts | 10 +- packages/frontend/src/scripts/use-form.ts | 55 + packages/frontend/src/store.ts | 42 +- packages/frontend/src/stream.ts | 11 +- packages/frontend/src/style.scss | 162 +- packages/frontend/src/timelines.ts | 56 + .../src/ui/_common_/announcements.vue | 12 +- packages/frontend/src/ui/_common_/common.ts | 112 +- packages/frontend/src/ui/_common_/common.vue | 28 +- .../src/ui/_common_/navbar-for-mobile.vue | 43 +- packages/frontend/src/ui/_common_/navbar.vue | 154 +- .../src/ui/_common_/statusbar-federation.vue | 2 +- .../src/ui/_common_/statusbar-rss.vue | 2 +- .../src/ui/_common_/statusbar-user-list.vue | 2 +- .../frontend/src/ui/_common_/statusbars.vue | 20 +- .../src/ui/_common_/stream-indicator.vue | 4 +- packages/frontend/src/ui/_common_/upload.vue | 4 +- packages/frontend/src/ui/classic.header.vue | 15 +- packages/frontend/src/ui/classic.sidebar.vue | 18 +- packages/frontend/src/ui/classic.vue | 42 +- packages/frontend/src/ui/deck.vue | 63 +- .../frontend/src/ui/deck/antenna-column.vue | 40 +- .../frontend/src/ui/deck/channel-column.vue | 5 +- packages/frontend/src/ui/deck/column.vue | 151 +- packages/frontend/src/ui/deck/deck-store.ts | 24 +- .../frontend/src/ui/deck/direct-column.vue | 2 +- packages/frontend/src/ui/deck/list-column.vue | 43 +- packages/frontend/src/ui/deck/main-column.vue | 9 +- .../frontend/src/ui/deck/mentions-column.vue | 2 +- .../src/ui/deck/notifications-column.vue | 7 +- .../src/ui/deck/role-timeline-column.vue | 6 +- packages/frontend/src/ui/deck/tl-column.vue | 83 +- .../frontend/src/ui/deck/widgets-column.vue | 6 +- packages/frontend/src/ui/minimum.vue | 2 +- packages/frontend/src/ui/universal.vue | 65 +- packages/frontend/src/ui/visitor.vue | 26 +- packages/frontend/src/ui/zen.vue | 14 +- .../frontend/src/widgets/WidgetAiscript.vue | 6 +- .../src/widgets/WidgetBirthdayFollowings.vue | 8 +- .../frontend/src/widgets/WidgetCalendar.vue | 6 +- .../frontend/src/widgets/WidgetFederation.vue | 6 +- .../src/widgets/WidgetInstanceCloud.vue | 2 +- .../src/widgets/WidgetInstanceInfo.vue | 2 +- .../frontend/src/widgets/WidgetJobQueue.vue | 8 +- packages/frontend/src/widgets/WidgetMemo.vue | 4 +- .../src/widgets/WidgetNotifications.vue | 5 +- .../src/widgets/WidgetOnlineUsers.vue | 4 +- packages/frontend/src/widgets/WidgetRss.vue | 6 +- .../frontend/src/widgets/WidgetRssTicker.vue | 8 +- .../frontend/src/widgets/WidgetSlideshow.vue | 2 +- .../frontend/src/widgets/WidgetTimeline.vue | 50 +- .../frontend/src/widgets/WidgetTrends.vue | 6 +- .../frontend/src/widgets/WidgetUserList.vue | 2 +- .../src/widgets/server-metric/cpu-mem.vue | 2 +- .../src/widgets/server-metric/net.vue | 2 +- packages/frontend/test/emoji.test.ts | 2 +- packages/frontend/test/i18n.test.ts | 54 + packages/frontend/test/scroll.test.ts | 2 +- packages/frontend/tsconfig.json | 4 +- packages/frontend/vite.config.local-dev.ts | 28 +- packages/frontend/vite.config.ts | 11 +- packages/misskey-bubble-game/.eslintignore | 8 - packages/misskey-bubble-game/.eslintrc.cjs | 9 - packages/misskey-bubble-game/build.js | 33 +- packages/misskey-bubble-game/eslint.config.js | 28 + packages/misskey-bubble-game/package.json | 4 +- packages/misskey-bubble-game/src/game.ts | 30 +- packages/misskey-js/.eslintignore | 8 - packages/misskey-js/.eslintrc.cjs | 9 - packages/misskey-js/README.md | 2 +- packages/misskey-js/build.js | 33 +- packages/misskey-js/eslint.config.js | 29 + packages/misskey-js/etc/misskey-js.api.md | 293 +- packages/misskey-js/generator/.eslintrc.cjs | 9 - .../misskey-js/generator/eslint.config.js | 17 + packages/misskey-js/generator/package.json | 14 +- .../misskey-js/generator/src/generator.ts | 56 +- packages/misskey-js/package.json | 29 +- packages/misskey-js/src/acct.ts | 3 +- packages/misskey-js/src/api.ts | 75 +- packages/misskey-js/src/api.types.ts | 40 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 46 + packages/misskey-js/src/autogen/endpoint.ts | 22 +- .../misskey-js/src/autogen/endpointErrors.ts | 50 +- packages/misskey-js/src/autogen/entities.ts | 9 + packages/misskey-js/src/autogen/types.ts | 412 +- packages/misskey-js/src/consts.ts | 160 +- packages/misskey-js/src/entities.ts | 90 +- packages/misskey-js/src/index.ts | 30 +- packages/misskey-js/src/note.ts | 12 + .../src/scripts => misskey-js/src}/nyaize.ts | 6 +- packages/misskey-js/src/streaming.ts | 65 +- packages/misskey-js/src/streaming.types.ts | 24 +- packages/misskey-js/test-d/api.ts | 4 +- packages/misskey-js/test/api.ts | 92 +- packages/misskey-js/tsconfig.json | 1 + packages/misskey-reversi/.eslintignore | 8 - packages/misskey-reversi/.eslintrc.cjs | 10 - packages/misskey-reversi/build.js | 33 +- packages/misskey-reversi/eslint.config.js | 24 + packages/misskey-reversi/package.json | 4 +- packages/misskey-reversi/src/game.ts | 11 +- packages/shared/.eslintrc.js | 7 - packages/shared/eslint.config.js | 28 + packages/shared/package.json | 3 + packages/sw/.eslintrc.cjs | 20 - packages/sw/build.js | 4 +- packages/sw/eslint.config.js | 32 + packages/sw/package.json | 12 +- .../sw/src/scripts/create-notification.ts | 95 +- .../sw/src/scripts/get-account-from-id.ts | 5 +- packages/sw/src/scripts/i18n.ts | 37 - packages/sw/src/scripts/lang.ts | 5 +- packages/sw/src/scripts/operations.ts | 15 +- packages/sw/src/sw.ts | 11 +- packages/sw/src/types.ts | 3 +- packages/sw/tsconfig.json | 3 +- pnpm-lock.yaml | 13821 ++++++++-------- pnpm-workspace.yaml | 2 + scripts/build-assets.mjs | 2 + scripts/changelog-checker/.eslintrc.cjs | 9 - scripts/changelog-checker/eslint.config.js | 17 + scripts/changelog-checker/package-lock.json | 382 +- scripts/changelog-checker/package.json | 2 +- scripts/clean-all.js | 6 + scripts/clean.js | 2 + scripts/dev.mjs | 12 + 1031 files changed, 41072 insertions(+), 16771 deletions(-) create mode 100644 .config/cypress-devcontainer.yml rename .devcontainer/{docker-compose.yml => compose.yml} (98%) rename docker-compose.local-db.yml => compose.local-db.yml (98%) rename docker-compose_example.yml => compose_example.yml (97%) rename {packages/frontend/src/components => idea}/MkAbuseReport.stories.impl.ts (88%) create mode 100644 idea/MkDisableSection.vue create mode 100644 idea/README.md delete mode 160000 misskey-assets delete mode 100644 packages/backend/.eslintignore delete mode 100644 packages/backend/.eslintrc.cjs create mode 100644 packages/backend/assets/api-doc.html create mode 100644 packages/backend/assets/embed.js delete mode 100644 packages/backend/assets/redoc.html create mode 100644 packages/backend/assets/tabler-badges/login-2.png create mode 100644 packages/backend/eslint.config.js create mode 100644 packages/backend/migration/1716197366117-MediaSilenceForHosts.js create mode 100644 packages/backend/migration/1721666053703-fixDriveUrl.js create mode 100644 packages/backend/migration/1723944246767-followedMessage.js create mode 100644 packages/backend/migration/1726804538569-reactions-buffering.js create mode 100644 packages/backend/migration/1727491883993-user-score.js create mode 100644 packages/backend/migration/1727512908322-meta-federation.js create mode 100644 packages/backend/migration/1728085812127-refine-abuse-user-report.js create mode 100644 packages/backend/migration/1728550878802-testcaptcha.js create mode 100644 packages/backend/src/core/FlashService.ts create mode 100644 packages/backend/src/core/ReactionsBufferingService.ts create mode 100644 packages/backend/src/core/UserRenoteMutingService.ts create mode 100644 packages/backend/src/core/UserSearchService.ts create mode 100644 packages/backend/src/core/WebhookTestService.ts create mode 100644 packages/backend/src/misc/collapsed-queue.ts create mode 100644 packages/backend/src/misc/json-value.ts create mode 100644 packages/backend/src/queue/processors/BakeBufferedReactionsProcessorService.ts create mode 100644 packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts create mode 100644 packages/backend/src/server/api/SigninWithPasskeyApiService.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/forward-abuse-user-report.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/test.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/update-abuse-user-report.ts create mode 100644 packages/backend/src/server/api/endpoints/i/webhooks/test.ts create mode 100644 packages/backend/src/server/web/boot.embed.js create mode 100644 packages/backend/src/server/web/style.embed.css create mode 100644 packages/backend/src/server/web/views/base-embed.pug delete mode 100644 packages/backend/test-server/.eslintrc.cjs create mode 100644 packages/backend/test-server/eslint.config.js delete mode 100644 packages/backend/test/.eslintrc.cjs rename packages/backend/test/{docker-compose.yml => compose.yml} (94%) create mode 100644 packages/backend/test/e2e/synalio/user-create.ts create mode 100644 packages/backend/test/eslint.config.js create mode 100644 packages/backend/test/resources/192.jpg create mode 100644 packages/backend/test/resources/192.png delete mode 100644 packages/backend/test/resources/Lenna.jpg delete mode 100644 packages/backend/test/resources/Lenna.png create mode 100644 packages/backend/test/unit/FlashService.ts create mode 100644 packages/backend/test/unit/SigninWithPasskeyApiService.ts create mode 100644 packages/backend/test/unit/UserSearchService.ts create mode 100644 packages/backend/test/unit/UserWebhookService.ts create mode 100644 packages/backend/test/unit/WebhookTestService.ts create mode 100644 packages/backend/test/unit/queue/processors/CheckModeratorsActivityProcessorService.ts create mode 100644 packages/frontend-embed/.gitignore create mode 100644 packages/frontend-embed/@types/global.d.ts create mode 100644 packages/frontend-embed/@types/theme.d.ts create mode 100644 packages/frontend-embed/assets/dummy.png create mode 100644 packages/frontend-embed/eslint.config.js create mode 100644 packages/frontend-embed/package.json create mode 100644 packages/frontend-embed/src/boot.ts create mode 100644 packages/frontend-embed/src/components/EmA.vue create mode 100644 packages/frontend-embed/src/components/EmAcct.vue create mode 100644 packages/frontend-embed/src/components/EmAvatar.vue create mode 100644 packages/frontend-embed/src/components/EmCustomEmoji.vue create mode 100644 packages/frontend-embed/src/components/EmEmoji.vue create mode 100644 packages/frontend-embed/src/components/EmError.vue create mode 100644 packages/frontend-embed/src/components/EmImgWithBlurhash.vue create mode 100644 packages/frontend-embed/src/components/EmInstanceTicker.vue create mode 100644 packages/frontend-embed/src/components/EmLink.vue create mode 100644 packages/frontend-embed/src/components/EmLoading.vue create mode 100644 packages/frontend-embed/src/components/EmMediaBanner.vue create mode 100644 packages/frontend-embed/src/components/EmMediaImage.vue create mode 100644 packages/frontend-embed/src/components/EmMediaList.vue create mode 100644 packages/frontend-embed/src/components/EmMediaVideo.vue create mode 100644 packages/frontend-embed/src/components/EmMention.vue create mode 100644 packages/frontend-embed/src/components/EmMfm.ts create mode 100644 packages/frontend-embed/src/components/EmNote.vue create mode 100644 packages/frontend-embed/src/components/EmNoteDetailed.vue create mode 100644 packages/frontend-embed/src/components/EmNoteHeader.vue create mode 100644 packages/frontend-embed/src/components/EmNoteSimple.vue create mode 100644 packages/frontend-embed/src/components/EmNoteSub.vue create mode 100644 packages/frontend-embed/src/components/EmNotes.vue create mode 100644 packages/frontend-embed/src/components/EmPagination.vue create mode 100644 packages/frontend-embed/src/components/EmPoll.vue create mode 100644 packages/frontend-embed/src/components/EmReactionIcon.vue create mode 100644 packages/frontend-embed/src/components/EmReactionsViewer.reaction.vue create mode 100644 packages/frontend-embed/src/components/EmReactionsViewer.vue create mode 100644 packages/frontend-embed/src/components/EmSubNoteContent.vue create mode 100644 packages/frontend-embed/src/components/EmTime.vue create mode 100644 packages/frontend-embed/src/components/EmTimelineContainer.vue create mode 100644 packages/frontend-embed/src/components/EmUrl.vue create mode 100644 packages/frontend-embed/src/components/EmUserName.vue create mode 100644 packages/frontend-embed/src/components/I18n.vue create mode 100644 packages/frontend-embed/src/custom-emojis.ts create mode 100644 packages/frontend-embed/src/di.ts create mode 100644 packages/frontend-embed/src/i18n.ts create mode 100644 packages/frontend-embed/src/index.html create mode 100644 packages/frontend-embed/src/misskey-api.ts create mode 100644 packages/frontend-embed/src/pages/clip.vue create mode 100644 packages/frontend-embed/src/pages/not-found.vue create mode 100644 packages/frontend-embed/src/pages/note.vue create mode 100644 packages/frontend-embed/src/pages/tag.vue create mode 100644 packages/frontend-embed/src/pages/user-timeline.vue create mode 100644 packages/frontend-embed/src/post-message.ts create mode 100644 packages/frontend-embed/src/server-context.ts create mode 100644 packages/frontend-embed/src/server-metadata.ts create mode 100644 packages/frontend-embed/src/style.scss create mode 100644 packages/frontend-embed/src/theme.ts create mode 100644 packages/frontend-embed/src/ui.vue create mode 100644 packages/frontend-embed/src/utils.ts create mode 100644 packages/frontend-embed/src/workers/draw-blurhash.ts create mode 100644 packages/frontend-embed/src/workers/test-webgl2.ts create mode 100644 packages/frontend-embed/src/workers/tsconfig.json create mode 100644 packages/frontend-embed/tsconfig.json create mode 100644 packages/frontend-embed/vite.config.local-dev.ts create mode 100644 packages/frontend-embed/vite.config.ts create mode 100644 packages/frontend-embed/vite.json5.ts create mode 100644 packages/frontend-embed/vue-shims.d.ts create mode 100644 packages/frontend-shared/.gitignore create mode 100644 packages/frontend-shared/@types/global.d.ts create mode 100644 packages/frontend-shared/build.js create mode 100644 packages/frontend-shared/eslint.config.js rename packages/{frontend/src/scripts => frontend-shared/js}/collapsed.ts (86%) rename packages/{frontend/src => frontend-shared/js}/config.ts (51%) rename packages/{frontend/src => frontend-shared/js}/const.ts (93%) create mode 100644 packages/frontend-shared/js/embed-page.ts rename packages/{frontend/src/scripts => frontend-shared/js}/emoji-base.ts (87%) rename packages/{frontend/src => frontend-shared/js}/emojilist.json (100%) rename packages/{frontend/src/scripts => frontend-shared/js}/emojilist.ts (96%) rename packages/{frontend/src/scripts => frontend-shared/js}/extract-avg-color-from-blurhash.ts (100%) rename packages/{frontend/src/scripts => frontend-shared/js}/i18n.ts (78%) create mode 100644 packages/frontend-shared/js/intl-const.ts create mode 100644 packages/frontend-shared/js/is-link.ts create mode 100644 packages/frontend-shared/js/media-proxy.ts rename packages/{frontend/src/scripts => frontend-shared/js}/scroll.ts (75%) rename packages/{frontend/src/scripts => frontend-shared/js}/url.ts (55%) rename packages/{frontend/src/scripts => frontend-shared/js}/use-document-visibility.ts (85%) rename packages/{frontend/src/scripts => frontend-shared/js}/use-interval.ts (100%) rename packages/{frontend/src/scripts => frontend-shared/js}/worker-multi-dispatch.ts (84%) create mode 100644 packages/frontend-shared/package.json rename packages/{frontend/src => frontend-shared}/themes/_dark.json5 (85%) rename packages/{frontend/src => frontend-shared}/themes/_light.json5 (86%) rename packages/{frontend/src => frontend-shared}/themes/d-astro.json5 (82%) rename packages/{frontend/src => frontend-shared}/themes/d-botanical.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-cherry.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-dark.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-future.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-green-lime.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-green-orange.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-ice.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-persimmon.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/d-u0.json5 (89%) rename packages/{frontend/src => frontend-shared}/themes/l-apricot.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-botanical.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-cherry.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-coffee.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-light.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-rainy.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-sushi.json5 (100%) rename packages/{frontend/src => frontend-shared}/themes/l-u0.json5 (92%) rename packages/{frontend/src => frontend-shared}/themes/l-vivid.json5 (82%) create mode 100644 packages/frontend-shared/tsconfig.json delete mode 100644 packages/frontend/.eslintrc.cjs create mode 100644 packages/frontend/assets/testcaptcha.png create mode 100644 packages/frontend/eslint.config.js create mode 100644 packages/frontend/src/components/MkAntennaEditor.stories.impl.ts rename packages/frontend/src/{pages/my-antennas/editor.vue => components/MkAntennaEditor.vue} (63%) create mode 100644 packages/frontend/src/components/MkAntennaEditorDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkAntennaEditorDialog.vue create mode 100644 packages/frontend/src/components/MkDateSeparatedList.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDivider.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDonation.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDrive.file.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDrive.folder.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDrive.navFolder.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDrive.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDriveFileThumbnail.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDriveSelectDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkDriveWindow.stories.impl.ts create mode 100644 packages/frontend/src/components/MkEmbedCodeGenDialog.vue create mode 100644 packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts create mode 100644 packages/frontend/src/components/MkEmojiPicker.stories.impl.ts create mode 100644 packages/frontend/src/components/MkEmojiPickerDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkExtensionInstaller.stories.impl.ts create mode 100644 packages/frontend/src/components/MkExtensionInstaller.vue create mode 100644 packages/frontend/src/components/MkFlashPreview.stories.impl.ts create mode 100644 packages/frontend/src/components/MkFormFooter.vue create mode 100644 packages/frontend/src/components/MkFukidashi.vue create mode 100644 packages/frontend/src/components/MkPreview.vue create mode 100644 packages/frontend/src/components/MkSignin.input.vue create mode 100644 packages/frontend/src/components/MkSignin.passkey.vue create mode 100644 packages/frontend/src/components/MkSignin.password.vue create mode 100644 packages/frontend/src/components/MkSignin.totp.vue rename packages/frontend/src/components/global/{MkMisskeyFlavoredMarkdown.stories.impl.ts => MkMfm.stories.impl.ts} (78%) rename packages/frontend/src/components/global/{MkMisskeyFlavoredMarkdown.ts => MkMfm.ts} (93%) create mode 100644 packages/frontend/src/pages/about.overview.vue delete mode 100644 packages/frontend/src/pages/admin/instance-block.vue delete mode 100644 packages/frontend/src/pages/admin/other-settings.vue create mode 100644 packages/frontend/src/pages/admin/overview.ap-requests.stories.impl.ts create mode 100644 packages/frontend/src/pages/admin/performance.vue delete mode 100644 packages/frontend/src/pages/admin/proxy-account.vue delete mode 100644 packages/frontend/src/pages/follow.vue create mode 100644 packages/frontend/src/pages/lookup.vue create mode 100644 packages/frontend/src/pages/page-editor/common.ts create mode 100644 packages/frontend/src/pages/preview.vue create mode 100644 packages/frontend/src/pages/search.stories.impl.ts create mode 100644 packages/frontend/src/pages/welcome.timeline.note.vue create mode 100644 packages/frontend/src/scripts/check-permissions.ts create mode 100644 packages/frontend/src/scripts/focus-trap.ts create mode 100644 packages/frontend/src/scripts/get-appear-note.ts create mode 100644 packages/frontend/src/scripts/get-dom-node-or-null.ts create mode 100644 packages/frontend/src/scripts/get-embed-code.ts delete mode 100644 packages/frontend/src/scripts/keycode.ts create mode 100644 packages/frontend/src/scripts/player-url-transform.ts create mode 100644 packages/frontend/src/scripts/reload-ask.ts delete mode 100644 packages/frontend/src/scripts/safe-parse.ts delete mode 100644 packages/frontend/src/scripts/safe-uri-decode.ts create mode 100644 packages/frontend/src/scripts/stream-mock.ts create mode 100644 packages/frontend/src/scripts/use-form.ts create mode 100644 packages/frontend/src/timelines.ts create mode 100644 packages/frontend/test/i18n.test.ts delete mode 100644 packages/misskey-bubble-game/.eslintignore delete mode 100644 packages/misskey-bubble-game/.eslintrc.cjs create mode 100644 packages/misskey-bubble-game/eslint.config.js delete mode 100644 packages/misskey-js/.eslintignore delete mode 100644 packages/misskey-js/.eslintrc.cjs create mode 100644 packages/misskey-js/eslint.config.js delete mode 100644 packages/misskey-js/generator/.eslintrc.cjs create mode 100644 packages/misskey-js/generator/eslint.config.js create mode 100644 packages/misskey-js/src/note.ts rename packages/{frontend/src/scripts => misskey-js/src}/nyaize.ts (82%) delete mode 100644 packages/misskey-reversi/.eslintignore delete mode 100644 packages/misskey-reversi/.eslintrc.cjs create mode 100644 packages/misskey-reversi/eslint.config.js delete mode 100644 packages/shared/.eslintrc.js create mode 100644 packages/shared/eslint.config.js create mode 100644 packages/shared/package.json delete mode 100644 packages/sw/.eslintrc.cjs create mode 100644 packages/sw/eslint.config.js delete mode 100644 packages/sw/src/scripts/i18n.ts delete mode 100644 scripts/changelog-checker/.eslintrc.cjs create mode 100644 scripts/changelog-checker/eslint.config.js diff --git a/.config/cypress-devcontainer.yml b/.config/cypress-devcontainer.yml new file mode 100644 index 0000000000..3907615f73 --- /dev/null +++ b/.config/cypress-devcontainer.yml @@ -0,0 +1,224 @@ +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Misskey configuration +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# ┌────────────────────────┐ +#───┘ Initial Setup Password └───────────────────────────────────────────────────── + +# Password to initiate setting up admin account. +# It will not be used after the initial setup is complete. +# +# Be sure to change this when you set up Misskey via the Internet. +# +# The provider of the service who sets up Misskey on behalf of the customer should +# set this value to something unique when generating the Misskey config file, +# and provide it to the customer. +setupPassword: example_password_please_change_this_or_you_will_get_hacked + +# ┌─────┐ +#───┘ URL └───────────────────────────────────────────────────── + +# Final accessible URL seen by a user. +url: 'http://misskey.local' + +# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE +# URL SETTINGS AFTER THAT! + +# ┌───────────────────────┐ +#───┘ Port and TLS settings └─────────────────────────────────── + +# +# Misskey requires a reverse proxy to support HTTPS connections. +# +# +----- https://example.tld/ ------------+ +# +------+ |+-------------+ +----------------+| +# | User | ---> || Proxy (443) | ---> | Misskey (3000) || +# +------+ |+-------------+ +----------------+| +# +---------------------------------------+ +# +# You need to set up a reverse proxy. (e.g. nginx) +# An encrypted connection with HTTPS is highly recommended +# because tokens may be transferred in GET requests. + +# The port that your Misskey server should listen on. +port: 61812 + +# ┌──────────────────────────┐ +#───┘ PostgreSQL configuration └──────────────────────────────── + +db: + host: db + port: 5432 + + # Database name + db: misskey + + # Auth + user: postgres + pass: postgres + + # Whether disable Caching queries + #disableCache: true + + # Extra Connection options + #extra: + # ssl: true + +dbReplications: false + +# You can configure any number of replicas here +#dbSlaves: +# - +# host: +# port: +# db: +# user: +# pass: +# - +# host: +# port: +# db: +# user: +# pass: + +# ┌─────────────────────┐ +#───┘ Redis configuration └───────────────────────────────────── + +redis: + host: redis + port: 6379 + #family: 0 # 0=Both, 4=IPv4, 6=IPv6 + #pass: example-pass + #prefix: example-prefix + #db: 1 + +#redisForPubsub: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + +#redisForJobQueue: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + +#redisForTimelines: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + +#redisForReactions: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + +# ┌───────────────────────────┐ +#───┘ MeiliSearch configuration └───────────────────────────── + +#meilisearch: +# host: meilisearch +# port: 7700 +# apiKey: '' +# ssl: true +# index: '' + +# ┌───────────────┐ +#───┘ ID generation └─────────────────────────────────────────── + +# You can select the ID generation method. +# You don't usually need to change this setting, but you can +# change it according to your preferences. + +# Available methods: +# aid ... Short, Millisecond accuracy +# aidx ... Millisecond accuracy +# meid ... Similar to ObjectID, Millisecond accuracy +# ulid ... Millisecond accuracy +# objectid ... This is left for backward compatibility + +# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE +# ID SETTINGS AFTER THAT! + +id: 'aidx' + +# ┌────────────────┐ +#───┘ Error tracking └────────────────────────────────────────── + +# Sentry is available for error tracking. +# See the Sentry documentation for more details on options. + +#sentryForBackend: +# enableNodeProfiling: true +# options: +# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' + +#sentryForFrontend: +# options: +# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' + +# ┌─────────────────────┐ +#───┘ Other configuration └───────────────────────────────────── + +# Whether disable HSTS +#disableHsts: true + +# Number of worker processes +#clusterLimit: 1 + +# Job concurrency per worker +# deliverJobConcurrency: 128 +# inboxJobConcurrency: 16 + +# Job rate limiter +# deliverJobPerSec: 128 +# inboxJobPerSec: 32 + +# Job attempts +# deliverJobMaxAttempts: 12 +# inboxJobMaxAttempts: 8 + +# IP address family used for outgoing request (ipv4, ipv6 or dual) +#outgoingAddressFamily: ipv4 + +# Proxy for HTTP/HTTPS +#proxy: http://127.0.0.1:3128 + +proxyBypassHosts: + - api.deepl.com + - api-free.deepl.com + - www.recaptcha.net + - hcaptcha.com + - challenges.cloudflare.com + +# Proxy for SMTP/SMTPS +#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT +#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 +#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 + +# Media Proxy +#mediaProxy: https://example.com/proxy + +# Proxy remote files (default: true) +proxyRemoteFiles: true + +# Sign to ActivityPub GET request (default: true) +signToActivityPubGet: true + +allowedPrivateNetworks: [ + '127.0.0.1/32' +] + +# Upload or download file size limits (bytes) +#maxFileSize: 262144000 diff --git a/.config/docker_example.env b/.config/docker_example.env index 4fe8e76b78..c61248da2e 100644 --- a/.config/docker_example.env +++ b/.config/docker_example.env @@ -1,5 +1,11 @@ +# misskey settings +# MISSKEY_URL=https://example.tld/ + # db settings POSTGRES_PASSWORD=example-misskey-pass +# DATABASE_PASSWORD=${POSTGRES_PASSWORD} POSTGRES_USER=example-misskey-user +# DATABASE_USER=${POSTGRES_USER} POSTGRES_DB=misskey +# DATABASE_DB=${POSTGRES_DB} DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}" diff --git a/.config/docker_example.yml b/.config/docker_example.yml index 42ac18de1b..3f8e5734ce 100644 --- a/.config/docker_example.yml +++ b/.config/docker_example.yml @@ -6,6 +6,7 @@ #───┘ URL └───────────────────────────────────────────────────── # Final accessible URL seen by a user. +# You can set url from an environment variable instead. url: https://example.tld/ # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE @@ -38,9 +39,11 @@ db: port: 5432 # Database name + # You can set db from an environment variable instead. db: misskey # Auth + # You can set user and pass from environment variables instead. user: example-misskey-user pass: example-misskey-pass @@ -103,6 +106,14 @@ redis: # #prefix: example-prefix # #db: 1 +#redisForReactions: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── diff --git a/.config/example.yml b/.config/example.yml index b11cbd1373..60a6a0aa71 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -59,6 +59,20 @@ # # publishTarballInsteadOfProvideRepositoryUrl: true +# ┌────────────────────────┐ +#───┘ Initial Setup Password └───────────────────────────────────────────────────── + +# Password to initiate setting up admin account. +# It will not be used after the initial setup is complete. +# +# Be sure to change this when you set up Misskey via the Internet. +# +# The provider of the service who sets up Misskey on behalf of the customer should +# set this value to something unique when generating the Misskey config file, +# and provide it to the customer. +# +# setupPassword: example_password_please_change_this_or_you_will_get_hacked + # ┌─────┐ #───┘ URL └───────────────────────────────────────────────────── @@ -172,6 +186,16 @@ redis: # # You can specify more ioredis options... # #username: example-username +#redisForReactions: +# host: localhost +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 +# # You can specify more ioredis options... +# #username: example-username + # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/compose.yml similarity index 98% rename from .devcontainer/docker-compose.yml rename to .devcontainer/compose.yml index a52d086fb6..d02d2a8f4a 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: app: build: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 344edbd65d..fbf959d449 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,11 +1,11 @@ { "name": "Misskey", - "dockerComposeFile": "docker-compose.yml", + "dockerComposeFile": "compose.yml", "service": "app", "workspaceFolder": "/workspace", "features": { "ghcr.io/devcontainers/features/node:1": { - "version": "20.12.2" + "version": "20.16.0" }, "ghcr.io/devcontainers-contrib/features/corepack:1": {} }, diff --git a/.devcontainer/devcontainer.yml b/.devcontainer/devcontainer.yml index beefcfd0a2..3eb4fc2879 100644 --- a/.devcontainer/devcontainer.yml +++ b/.devcontainer/devcontainer.yml @@ -103,6 +103,14 @@ redis: # #prefix: example-prefix # #db: 1 +#redisForReactions: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── diff --git a/.devcontainer/init.sh b/.devcontainer/init.sh index 55fb1e6fa6..e02a533c15 100755 --- a/.devcontainer/init.sh +++ b/.devcontainer/init.sh @@ -3,6 +3,8 @@ set -xe sudo chown node node_modules +sudo apt-get update +sudo apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb git config --global --add safe.directory /workspace git submodule update --init corepack install @@ -12,3 +14,4 @@ pnpm install --frozen-lockfile cp .devcontainer/devcontainer.yml .config/default.yml pnpm build pnpm migrate +pnpm exec cypress install diff --git a/.dockerignore b/.dockerignore index 1de0c7982b..f204349160 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,12 +7,11 @@ Dockerfile build/ built/ db/ -docker-compose.yml +.devcontainer/compose.yml node_modules/ packages/*/node_modules redis/ files/ -misskey-assets/ fluent-emojis/ .pnp.* @@ -28,4 +27,4 @@ fluent-emojis/ .idea/ packages/*/.vscode/ -packages/backend/test/docker-compose.yml +packages/backend/test/compose.yml diff --git a/.github/ISSUE_TEMPLATE/01_bug-report.yml b/.github/ISSUE_TEMPLATE/01_bug-report.yml index ac2b39cc12..315e712c30 100644 --- a/.github/ISSUE_TEMPLATE/01_bug-report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug-report.yml @@ -53,8 +53,8 @@ body: Examples: * Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4 * Browser: Chrome 113.0.5672.126 - * Server URL: misskey.io - * Misskey: 13.x.x + * Server URL: misskey.example.com + * Misskey: 2024.x.x value: | * Model and OS of the device(s): * Browser: @@ -74,11 +74,11 @@ body: Examples: * Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment - * Misskey: 13.x.x + * Misskey: 2024.x.x * Node: 20.x.x * PostgreSQL: 15.x.x * Redis: 7.x.x - * OS and Architecture: Ubuntu 22.04.2 LTS aarch64 + * OS and Architecture: Ubuntu 24.04.2 LTS aarch64 value: | * Installation Method or Hosting Service: * Misskey: diff --git a/.github/misskey/test.yml b/.github/misskey/test.yml index 7a4aa4ae6c..3c807e8b9e 100644 --- a/.github/misskey/test.yml +++ b/.github/misskey/test.yml @@ -1,5 +1,7 @@ url: 'http://misskey.local' +setupPassword: example_password_please_change_this_or_you_will_get_hacked + # ローカルでテストするときにポートを被らないようにするためデフォルトのものとは変える(以下同じ) port: 61812 diff --git a/.github/workflows/api-misskey-js.yml b/.github/workflows/api-misskey-js.yml index 1b7b68b14f..8380a3bb23 100644 --- a/.github/workflows/api-misskey-js.yml +++ b/.github/workflows/api-misskey-js.yml @@ -4,10 +4,11 @@ on: push: paths: - packages/misskey-js/** + - .github/workflows/api-misskey-js.yml pull_request: paths: - packages/misskey-js/** - + - .github/workflows/api-misskey-js.yml jobs: report: @@ -20,7 +21,7 @@ jobs: - run: corepack enable - name: Setup Node.js - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml index f254af0d1f..44cc1a04f2 100644 --- a/.github/workflows/changelog-check.yml +++ b/.github/workflows/changelog-check.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout head uses: actions/checkout@v4.1.1 - name: Setup Node.js - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' diff --git a/.github/workflows/check-misskey-js-autogen.yml b/.github/workflows/check-misskey-js-autogen.yml index 39acad8bc3..f26c9a4d45 100644 --- a/.github/workflows/check-misskey-js-autogen.yml +++ b/.github/workflows/check-misskey-js-autogen.yml @@ -21,6 +21,7 @@ jobs: uses: actions/checkout@v4.1.1 with: submodules: true + persist-credentials: false ref: refs/pull/${{ github.event.pull_request.number }}/merge - name: setup pnpm @@ -28,7 +29,7 @@ jobs: - name: setup node id: setup-node - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: pnpm @@ -57,7 +58,7 @@ jobs: name: generated-misskey-js path: packages/misskey-js/generator/built/autogen - # pull_request_target safety: permissions: read-all, and there are no secrets used in this job + # pull_request_target safety: permissions: read-all, and no user codes are executed get-actual-misskey-js: runs-on: ubuntu-latest permissions: @@ -68,6 +69,7 @@ jobs: uses: actions/checkout@v4.1.1 with: submodules: true + persist-credentials: false ref: refs/pull/${{ github.event.pull_request.number }}/merge - name: Upload From Merged @@ -131,3 +133,7 @@ jobs: mode: delete message: "Thank you!" create_if_not_exists: false + + - name: Make failure if changes are detected + if: steps.check-changes.outputs.changes == 'true' + run: exit 1 diff --git a/.github/workflows/check-misskey-js-version.yml b/.github/workflows/check-misskey-js-version.yml index 325a893605..99c29ac974 100644 --- a/.github/workflows/check-misskey-js-version.yml +++ b/.github/workflows/check-misskey-js-version.yml @@ -6,12 +6,13 @@ on: paths: - packages/misskey-js/package.json - package.json + - .github/workflows/check-misskey-js-version.yml pull_request: branches: [ develop ] paths: - packages/misskey-js/package.json - package.json - + - .github/workflows/check-misskey-js-version.yml jobs: check-version: # ルートの package.json と packages/misskey-js/package.json のバージョンが一致しているかを確認する diff --git a/.github/workflows/check-spdx-license-id.yml b/.github/workflows/check-spdx-license-id.yml index 6cd8bf60d5..05582008b5 100644 --- a/.github/workflows/check-spdx-license-id.yml +++ b/.github/workflows/check-spdx-license-id.yml @@ -48,12 +48,16 @@ jobs: "packages/backend/migration" "packages/backend/src" "packages/backend/test" + "packages/frontend-shared/@types" + "packages/frontend-shared/js" "packages/frontend/.storybook" "packages/frontend/@types" "packages/frontend/lib" "packages/frontend/public" "packages/frontend/src" "packages/frontend/test" + "packages/frontend-embed/@types" + "packages/frontend-embed/src" "packages/misskey-bubble-game/src" "packages/misskey-reversi/src" "packages/sw/src" diff --git a/.github/workflows/dockle.yml b/.github/workflows/dockle.yml index 968971dd8d..c3dba4213d 100644 --- a/.github/workflows/dockle.yml +++ b/.github/workflows/dockle.yml @@ -22,7 +22,7 @@ jobs: sudo dpkg -i dockle.deb - run: | cp .config/docker_example.env .config/docker.env - cp ./docker-compose_example.yml ./docker-compose.yml + cp ./compose_example.yml ./compose.yml - run: | docker compose up -d web docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml index 9b9c8f11c4..1bcaa0d9c4 100644 --- a/.github/workflows/get-api-diff.yml +++ b/.github/workflows/get-api-diff.yml @@ -9,7 +9,6 @@ on: paths: - packages/backend/** - .github/workflows/get-api-diff.yml - jobs: get-from-misskey: runs-on: ubuntu-latest @@ -18,7 +17,7 @@ jobs: strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] api-json-name: [api-base.json, api-head.json] include: - api-json-name: api-base.json @@ -34,7 +33,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 76616ec5a7..90eb268dda 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,17 +8,26 @@ on: paths: - packages/backend/** - packages/frontend/** + - packages/frontend-shared/** + - packages/frontend-embed/** - packages/sw/** - packages/misskey-js/** - - packages/shared/.eslintrc.js + - packages/misskey-bubble-game/** + - packages/misskey-reversi/** + - packages/shared/eslint.config.js + - .github/workflows/lint.yml pull_request: paths: - packages/backend/** - packages/frontend/** + - packages/frontend-shared/** + - packages/frontend-embed/** - packages/sw/** - packages/misskey-js/** - - packages/shared/.eslintrc.js - + - packages/misskey-bubble-game/** + - packages/misskey-reversi/** + - packages/shared/eslint.config.js + - .github/workflows/lint.yml jobs: pnpm_install: runs-on: ubuntu-latest @@ -28,7 +37,7 @@ jobs: fetch-depth: 0 submodules: true - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' @@ -44,21 +53,34 @@ jobs: workspace: - backend - frontend + - frontend-shared + - frontend-embed - sw - misskey-js + - misskey-bubble-game + - misskey-reversi + env: + eslint-cache-version: v1 + eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }} steps: - uses: actions/checkout@v4.1.1 with: fetch-depth: 0 submodules: true - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' - run: corepack enable - run: pnpm i --frozen-lockfile - - run: pnpm --filter ${{ matrix.workspace }} run eslint + - name: Restore eslint cache + uses: actions/cache@v4.1.0 + with: + path: ${{ env.eslint-cache-path }} + key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }} + restore-keys: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}- + - run: pnpm --filter ${{ matrix.workspace }} run eslint --cache --cache-location ${{ env.eslint-cache-path }} --cache-strategy content typecheck: needs: [pnpm_install] @@ -68,6 +90,7 @@ jobs: matrix: workspace: - backend + - sw - misskey-js steps: - uses: actions/checkout@v4.1.1 @@ -75,14 +98,14 @@ jobs: fetch-depth: 0 submodules: true - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' - run: corepack enable - run: pnpm i --frozen-lockfile - run: pnpm --filter misskey-js run build - if: ${{ matrix.workspace == 'backend' }} + if: ${{ matrix.workspace == 'backend' || matrix.workspace == 'sw' }} - run: pnpm --filter misskey-reversi run build if: ${{ matrix.workspace == 'backend' }} - run: pnpm --filter ${{ matrix.workspace }} run typecheck diff --git a/.github/workflows/locale.yml b/.github/workflows/locale.yml index de2247e772..6bc8860a11 100644 --- a/.github/workflows/locale.yml +++ b/.github/workflows/locale.yml @@ -4,10 +4,11 @@ on: push: paths: - locales/** + - .github/workflows/locale.yml pull_request: paths: - locales/** - + - .github/workflows/locale.yml jobs: locale_verify: runs-on: ubuntu-latest @@ -18,7 +19,7 @@ jobs: fetch-depth: 0 submodules: true - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml index edfdab99e9..ffaf7bc038 100644 --- a/.github/workflows/on-release-created.yml +++ b/.github/workflows/on-release-created.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] steps: - uses: actions/checkout@v4.1.1 @@ -26,7 +26,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/release-edit-with-push.yml b/.github/workflows/release-edit-with-push.yml index 86ee0b3fb5..57657a4ba7 100644 --- a/.github/workflows/release-edit-with-push.yml +++ b/.github/workflows/release-edit-with-push.yml @@ -3,7 +3,7 @@ name: "Release Manager: sync changelog with PR" on: push: branches: - - release/** + - develop paths: - 'CHANGELOG.md' @@ -20,24 +20,29 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - # headがrelease/かつopenのPRを1つ取得 + # headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得 - name: Get PR run: | - echo "pr_number=$(gh pr list --limit 1 --head "$GITHUB_REF_NAME" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT + echo "pr_number=$(gh pr list --limit 1 --search "head:$GITHUB_REF_NAME base:$STABLE_BRANCH is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT id: get_pr + env: + STABLE_BRANCH: ${{ vars.STABLE_BRANCH }} - name: Get target version - uses: misskey-dev/release-manager-actions/.github/actions/get-target-version@v1 + if: steps.get_pr.outputs.pr_number != '' + uses: misskey-dev/release-manager-actions/.github/actions/get-target-version@v2 id: v # CHANGELOG.mdの内容を取得 - name: Get changelog - uses: misskey-dev/release-manager-actions/.github/actions/get-changelog@v1 + if: steps.get_pr.outputs.pr_number != '' + uses: misskey-dev/release-manager-actions/.github/actions/get-changelog@v2 with: version: ${{ steps.v.outputs.target_version }} id: changelog # PRのnotesを更新 - name: Update PR + if: steps.get_pr.outputs.pr_number != '' run: | gh pr edit "$PR_NUMBER" --body "$CHANGELOG" env: - CHANGELOG: ${{ steps.changelog.outputs.changelog }} PR_NUMBER: ${{ steps.get_pr.outputs.pr_number }} + CHANGELOG: ${{ steps.changelog.outputs.changelog }} diff --git a/.github/workflows/release-with-dispatch.yml b/.github/workflows/release-with-dispatch.yml index bc6448cb37..ed2f822269 100644 --- a/.github/workflows/release-with-dispatch.yml +++ b/.github/workflows/release-with-dispatch.yml @@ -17,6 +17,10 @@ on: type: boolean description: 'MERGE RELEASE BRANCH TO MAIN' default: false + start-rc: + type: boolean + description: 'Start Release Candidate' + default: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -33,18 +37,21 @@ jobs: pr_number: ${{ steps.get_pr.outputs.pr_number }} steps: - uses: actions/checkout@v4 - # headがrelease/かつopenのPRを1つ取得 + # headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得 - name: Get PRs run: | - echo "pr_number=$(gh pr list --limit 1 --search "head:release/ is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT + echo "pr_number=$(gh pr list --limit 1 --search "head:$GITHUB_REF_NAME base:$STABLE_BRANCH is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT id: get_pr + env: + STABLE_BRANCH: ${{ vars.STABLE_BRANCH }} merge: - uses: misskey-dev/release-manager-actions/.github/workflows/merge.yml@v1 + uses: misskey-dev/release-manager-actions/.github/workflows/merge.yml@v2 needs: get-pr if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge == true }} with: pr_number: ${{ needs.get-pr.outputs.pr_number }} + user: 'github-actions[bot]' package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }} # Text to prepend to the changelog # The first line must be `## Unreleased` @@ -53,39 +60,42 @@ jobs: ### General - - + ### Client - - + ### Server - - + use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }} indent: ${{ vars.INDENT }} secrets: RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }} RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} - RULESET_EDIT_APP_ID: ${{ secrets.RULESET_EDIT_APP_ID }} - RULESET_EDIT_APP_PRIVATE_KEY: ${{ secrets.RULESET_EDIT_APP_PRIVATE_KEY }} create-prerelease: - uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v1 + uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v2 needs: get-pr if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge != true }} with: pr_number: ${{ needs.get-pr.outputs.pr_number }} + user: 'github-actions[bot]' package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }} use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }} indent: ${{ vars.INDENT }} + draft_prerelease_channel: alpha + ready_start_prerelease_channel: beta + prerelease_channel: ${{ inputs.start-rc && 'rc' || '' }} secrets: RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }} RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} create-target: - uses: misskey-dev/release-manager-actions/.github/workflows/create-target.yml@v1 + uses: misskey-dev/release-manager-actions/.github/workflows/create-target.yml@v2 needs: get-pr if: ${{ needs.get-pr.outputs.pr_number == '' }} with: + user: 'github-actions[bot]' # The script for version increment. # process.env.CURRENT_VERSION: The current version. # @@ -118,8 +128,8 @@ jobs: package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }} use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }} indent: ${{ vars.INDENT }} + stable_branch: ${{ vars.STABLE_BRANCH }} + draft_prerelease_channel: alpha secrets: RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }} RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} - RULESET_EDIT_APP_ID: ${{ secrets.RULESET_EDIT_APP_ID }} - RULESET_EDIT_APP_PRIVATE_KEY: ${{ secrets.RULESET_EDIT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/release-with-ready.yml b/.github/workflows/release-with-ready.yml index a0fad0e336..e863b5e2e8 100644 --- a/.github/workflows/release-with-ready.yml +++ b/.github/workflows/release-with-ready.yml @@ -16,26 +16,31 @@ jobs: check: runs-on: ubuntu-latest outputs: - ref: ${{ steps.get_pr.outputs.ref }} + head: ${{ steps.get_pr.outputs.head }} + base: ${{ steps.get_pr.outputs.base }} steps: - uses: actions/checkout@v4 # PR情報を取得 - name: Get PR run: | - pr_json=$(gh pr view "$PR_NUMBER" --json isDraft,headRefName) - echo "ref=$(echo $pr_json | jq -r '.headRefName')" >> $GITHUB_OUTPUT + pr_json=$(gh pr view "$PR_NUMBER" --json isDraft,headRefName,baseRefName) + echo "head=$(echo $pr_json | jq -r '.headRefName')" >> $GITHUB_OUTPUT + echo "base=$(echo $pr_json | jq -r '.baseRefName')" >> $GITHUB_OUTPUT id: get_pr env: PR_NUMBER: ${{ github.event.pull_request.number }} release: - uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v1 + uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v2 needs: check - if: startsWith(needs.check.outputs.ref, 'release/') + if: needs.check.outputs.head == github.event.repository.default_branch && needs.check.outputs.base == vars.STABLE_BRANCH with: pr_number: ${{ github.event.pull_request.number }} + user: 'github-actions[bot]' package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }} use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }} indent: ${{ vars.INDENT }} + draft_prerelease_channel: alpha + ready_start_prerelease_channel: beta secrets: RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }} RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} diff --git a/.github/workflows/report-api-diff.yml b/.github/workflows/report-api-diff.yml index df9cc279e8..1170f898ce 100644 --- a/.github/workflows/report-api-diff.yml +++ b/.github/workflows/report-api-diff.yml @@ -70,18 +70,25 @@ jobs: - id: out-diff name: Build diff Comment run: | - cat <<- EOF > ./output.md - このPRによるapi.jsonの差分 -
- 差分はこちら - - \`\`\`diff - $(cat ./api.json.diff) - \`\`\` -
- - [Get diff files from Workflow Page](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}) - EOF + HEADER="このPRによるapi.jsonの差分" + FOOTER="[Get diff files from Workflow Page](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})" + DIFF_BYTES="$(stat ./api.json.diff -c '%s' | tr -d '\n')" + + echo "$HEADER" > ./output.md + + if (( "$DIFF_BYTES" <= 1 )); then + echo '差分はありません。' >> ./output.md + else + echo '
' >> ./output.md + echo '差分はこちら' >> ./output.md + echo >> ./output.md + echo '```diff' >> ./output.md + cat ./api.json.diff >> ./output.md + echo '```' >> ./output.md + echo '
' >> .output.md + fi + + echo "$FOOTER" >> ./output.md - uses: thollander/actions-comment-pull-request@v2 with: pr_number: ${{ steps.load-pr-num.outputs.pr-number }} diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index daa76509c8..c02f38ee0b 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -7,6 +7,11 @@ on: - develop - dev/storybook8 # for testing pull_request_target: + branches-ignore: + # Since pull requests targets master mostly is the "develop" branch. + # Storybook CI is checked on the "push" event of "develop" branch so it would cause a duplicate build. + # This is a waste of chromatic build quota, so we don't run storybook CI on pull requests targets master. + - master jobs: build: @@ -36,7 +41,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js 20.x - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index b1c54bb3e7..d95d6676f9 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -9,19 +9,20 @@ on: - packages/backend/** # for permissions - packages/misskey-js/** + - .github/workflows/test-backend.yml pull_request: paths: - packages/backend/** # for permissions - packages/misskey-js/** - + - .github/workflows/test-backend.yml jobs: unit: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] services: postgres: @@ -45,7 +46,7 @@ jobs: - name: Install FFmpeg uses: FedericoCarboni/setup-ffmpeg@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' @@ -70,7 +71,7 @@ jobs: strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] services: postgres: @@ -92,7 +93,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index 9d5053b82a..c68e1a8ef1 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -11,7 +11,7 @@ on: - packages/misskey-js/** # for e2e - packages/backend/** - + - .github/workflows/test-frontend.yml pull_request: paths: - packages/frontend/** @@ -19,14 +19,14 @@ on: - packages/misskey-js/** # for e2e - packages/backend/** - + - .github/workflows/test-frontend.yml jobs: vitest: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] steps: - uses: actions/checkout@v4.1.1 @@ -35,7 +35,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' @@ -61,7 +61,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [20.12.2] + node-version: [20.16.0] browser: [chrome] services: @@ -90,7 +90,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml index 2589d908b8..63e81f8c92 100644 --- a/.github/workflows/test-misskey-js.yml +++ b/.github/workflows/test-misskey-js.yml @@ -8,11 +8,12 @@ on: branches: [ develop ] paths: - packages/misskey-js/** + - .github/workflows/test-misskey-js.yml pull_request: branches: [ develop ] paths: - packages/misskey-js/** - + - .github/workflows/test-misskey-js.yml jobs: test: @@ -20,7 +21,7 @@ jobs: strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: @@ -30,7 +31,7 @@ jobs: - run: corepack enable - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml index 7f8db65293..0abc09c5a6 100644 --- a/.github/workflows/test-production.yml +++ b/.github/workflows/test-production.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] steps: - uses: actions/checkout@v4.1.1 @@ -25,7 +25,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/validate-api-json.yml b/.github/workflows/validate-api-json.yml index 24340e7d81..f809af1063 100644 --- a/.github/workflows/validate-api-json.yml +++ b/.github/workflows/validate-api-json.yml @@ -7,17 +7,18 @@ on: - develop paths: - packages/backend/** + - .github/workflows/validate-api-json.yml pull_request: paths: - packages/backend/** - + - .github/workflows/validate-api-json.yml jobs: validate-api-json: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.12.2] + node-version: [20.16.0] steps: - uses: actions/checkout@v4.1.1 @@ -26,7 +27,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.2 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.gitignore b/.gitignore index bdc14fea0a..b270d5cb3a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,13 +35,17 @@ coverage !/.config/example.yml !/.config/docker_example.yml !/.config/docker_example.env +!/.config/cypress-devcontainer.yml docker-compose.yml -!/.devcontainer/docker-compose.yml +compose.yml +.devcontainer/compose.yml +!/.devcontainer/compose.yml # misskey /build built built-test +js-built /data /.cache-loader /db @@ -59,6 +63,11 @@ ormconfig.json temp /packages/frontend/src/**/*.stories.ts tsdoc-metadata.json +misskey-assets + +# Vite temporary files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* # blender backups *.blend1 diff --git a/.gitmodules b/.gitmodules index 225a69a652..3218575273 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "misskey-assets"] - path = misskey-assets - url = https://github.com/misskey-dev/assets.git [submodule "fluent-emojis"] path = fluent-emojis url = https://github.com/misskey-dev/emojis.git diff --git a/.node-version b/.node-version index 87834047a6..8ce7030825 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -20.12.2 +20.16.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fae089649..b355712d94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,268 @@ -## Unreleased +## 2024.10.1 +### Note +- 悪質なユーザからサーバを守る措置の一環として、モデレータ権限を持つユーザの最終アクティブ日時を確認し、 +7日間活動していない場合は自動的に招待制へと移行(コントロールパネル -> モデレーション -> "誰でも新規登録できるようにする"をオフに変更)するようになりました。 +詳細な経緯は https://github.com/misskey-dev/misskey/issues/13437 をご確認ください。 + +### Client +- Enhance: l10nの更新 +- Fix: メールアドレス不要でCaptchaが有効な場合にアカウント登録完了後自動でのログインに失敗する問題を修正 + +### Server +- Feat: モデレータ権限を持つユーザが全員7日間活動しなかった場合は自動的に招待制へと移行するように ( #13437 ) +- Fix: `admin/emoji/update`エンドポイントのidのみ指定した時不正なエラーが発生するバグを修正 + +### Server +- Fix: キューのエラーログを簡略化するように + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/649) + +## 2024.10.0 + +### Note +- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません) + - ホスティングサービスを運営している場合は、コンフィグファイルを構築する際に`setupPassword`をランダムな値に設定し、ユーザーに通知するようにシステムを更新することをおすすめします。 + - なお、初期パスワードが設定されていない場合でも初期設定を行うことが可能です(UI上で初期パスワードの入力欄を空欄にすると続行できます)。 +- ユーザーデータを読み込む際の型が一部変更されました。 + - `twoFactorEnabled`, `usePasswordLessLogin`, `securityKeys`: 自分とモデレーター以外のユーザーからは取得できなくなりました + +### General +- Feat: サーバー初期設定時に初期パスワードを設定できるように +- Feat: 通報にモデレーションノートを残せるように +- Feat: 通報の解決種別を設定できるように +- Enhance: 通報の解決と転送を個別に行えるように +- Enhance: セキュリティ向上のため、サインイン時もCAPTCHAを求めるようになりました +- Enhance: 依存関係の更新 +- Enhance: l10nの更新 +- Enhance: Playの「人気」タブで10件以上表示可能に #14399 +- Fix: 連合のホワイトリストが正常に登録されない問題を修正 + +### Client +- Enhance: デザインの調整 +- Enhance: ログイン画面の認証フローを改善 +- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/657) + +### Server +- Enhance: セキュリティ向上のため、ログイン時にメール通知を行うように +- Enhance: 自分とモデレーター以外のユーザーから二要素認証関連のデータが取得できないように +- Enhance: 通報および通報解決時に送出されるSystemWebhookにユーザ情報を含めるように ( #14697 ) +- Fix: `admin/abuse-user-reports`エンドポイントのスキーマが間違っていた問題を修正 + +## 2024.9.0 + +### General +- Feat: ノート単体・ユーザーのノート・クリップのノートの埋め込み機能 + - 埋め込みコードやウェブサイトへの実装方法の詳細は https://misskey-hub.net/docs/for-users/features/embed/ をご覧ください +- Feat: パスキーでログインボタンを実装 (#14574) +- Feat: フォローされた際のメッセージを設定できるように +- Feat: 連合をホワイトリスト制にできるように +- Feat: UserWebhookとSystemWebhookのテスト送信機能を追加 (#14445) +- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/680) +- Feat: データエクスポートが完了した際に通知を発行するように +- Enhance: ユーザーによるコンテンツインポートの可否をロールポリシーで制御できるように +- Enhance: 依存関係の更新 +- Enhance: l10nの更新 + +### Client +- Enhance: サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように +- Enhance: アイコンデコレーション管理画面にプレビューを追加 +- Enhance: コントロールパネル内のファイル一覧でセンシティブなファイルを区別しやすく +- Enhance: ScratchpadにUIインスペクターを追加 +- Enhance: Play編集画面の項目の並びを少しリデザイン +- Enhance: 各種メニューをドロワー表示するかどうか設定可能に +- Enhance: AiScriptのMk:C:containerのオプションに`borderStyle`と`borderRadius`を追加 +- Enhance: CWでも絵文字をクリックしてメニューを表示できるように +- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正 +- Fix: コントロールパネル内のAp requests内のチャートの表示がおかしかった問題を修正 +- Fix: 月の違う同じ日はセパレータが表示されないのを修正 +- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正 + (Cherry-picked from https://github.com/taiyme/misskey/pull/265) +- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正 + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725) +- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正 +- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/bde6bb0bd2e8b0d027e724d2acdb8ae0585a8110) +- Fix: 一部画面のページネーションが動作しにくくなっていたのを修正 ( #12766 , #11449 ) + +### Server +- Feat: Misskey® Reactions Boost Technology™ (RBT)により、リアクションの作成負荷を低減することが可能に +- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように + - この変更により、公式フロントエンドでは入力の不備が内部エラーとして報告される代わりに一般的なエラーダイアログで報告されます +- Fix: ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正 +- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/26e0412fbb91447c37e8fb06ffb0487346063bb8) +- Fix: Continue importing from file if single emoji import fails +- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/8a982c61c01909e7540ff1be9f019df07c3f0624) +- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/634) +- Fix: ``を追って照会するのはOKレスポンスが返却された場合のみに + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/633) +- Fix: メールにスタイルが適用されていなかった問題を修正 + +## 2024.8.0 + +### General +- Enhance: モデレーターはすべてのユーザーのフォロー・フォロワーの一覧を見られるように +- Enhance: アカウントの削除のモデレーションログを残すように +- Enhance: 不適切なページ、ギャラリー、Playを管理者権限で削除できるように +- Fix: リモートユーザのフォロー・フォロワーの一覧が非公開設定の場合も表示できてしまう問題を修正 + +### Client +- Enhance: 「自分のPlay」ページにおいてPlayが非公開かどうかが一目でわかるように +- Enhance: 不適切なページ、ギャラリー、Playを通報できるように +- Fix: Play編集時に公開範囲が「パブリック」にリセットされる問題を修正 +- Fix: ページ遷移に失敗することがある問題を修正 +- Fix: iOSでユーザー名などがリンクとして誤検知される現象を抑制 +- Fix: mCaptchaを使用していてもbotプロテクションに関する警告が消えないのを修正 +- Fix: ユーザーのモデレーションページにおいてユーザー名にドットが入っているとシステムアカウントとして表示されてしまう問題を修正 +- Fix: 特定の条件下でノートの削除ボタンが出ないのを修正 + +### Server +- Enhance: 照会時にURLがhtmlかつheadタグ内に`rel="alternate"`, `type="application/activity+json"`の`link`タグがある場合に追ってリンク先を照会できるように +- Enhance: 凍結されたアカウントのフォローリクエストを表示しないように +- Fix: WSの`readAllNotifications` メッセージが `body` を持たない場合に動作しない問題 #14374 + - 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。 + - これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。 +- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正 +- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582) +- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679) +- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように + - キュー処理のつまりが改善される可能性があります +- Fix: リバーシの対局設定の変更が反映されないのを修正 +- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正 +- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正 + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/700) +- Fix: Prevent memory leak from memory caches (#14310) +- Fix: More reliable memory cache eviction (#14311) + +## 2024.7.0 + +### Note +- デッキUIの新着ノートをサウンドで通知する機能の追加(v2024.5.0)に伴い、以前から動作しなくなっていたクライアント設定内の「アンテナ受信」「チャンネル通知」サウンドを削除しました。 +- Streaming APIにて入力が不正な場合にはそのメッセージを無視するようになりました。 #14251 ### General - Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 +- Feat: ユーザーのアイコン/バナーの変更可否をロールで設定可能に + - 変更不可となっていても、設定済みのものを解除してデフォルト画像に戻すことは出来ます +- Feat: ユーザ作成時にSystemWebhookを送信可能に #14281 +- Feat: メディアサイレンスを実装 #13842 + - メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われ、カスタム絵文字が使用できないようになります。 +- Enhance: 管理画面でアーカイブにしたお知らせを表示・編集できるように - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 - Fix: Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題 +- Fix: デフォルトテーマに無効なテーマコードを入力するとUIが使用できなくなる問題を修正 +- 翻訳の更新 +- 依存関係の更新 ### Client +- Feat: ユーザーページから「このユーザーのノートを検索」できるように (#14128) +- Feat: 検索ページはクエリを受け付けるようになりました (#14128) +- Enhance: 検索ページのUI改善 (#14128) +- Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善 +- Enhance: 非ログイン時に他サーバーに遷移するアクションを追加 +- Enhance: 非ログイン時のハイライトTLのデザインを改善 +- Enhance: フロントエンドのアクセシビリティ改善 + (Based on https://github.com/taiyme/misskey/pull/226) +- Enhance: サーバー情報ページ・お問い合わせページを改善 + (Cherry-picked from https://github.com/taiyme/misskey/pull/238) +- Enhance: AiScriptを0.19.0にアップデート +- Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`) +- Enhance: センシティブなメディアを開く際に確認ダイアログを出せるように +- Enhance: 検索(ノート/ユーザー)で `#` から始まる文字列を入力すると、そのハッシュタグのノート/ユーザー一覧ページが表示できるように +- Enhance: 検索(ノート/ユーザー)において、入力に空白が含まれている場合は照会を行わないように +- Enhance: 検索(ノート/ユーザー)において、照会を行うかどうか、ハッシュタグのノート/ユーザー一覧ページを表示するかどうかの確認ダイアログを出すように +- Enhance: 検索(ノート/ユーザー)で `@` から始まる文字列(`@user@host`など)を入力すると、そのユーザーを照会できるように +- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように + (Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99) +- Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように +- Enhance: ブラウザのコンテキストメニューを使用できるように +- Enhance: 連合の「連合中」,「購読中」,「配信中」に対してブロックしているサーバー、配信停止しているサーバーを含めないように - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) - Fix: リバーシの対局を正しく共有できないことがある問題を修正 - Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正 +- Fix: アンテナの編集画面のボタンに隙間を追加 +- Fix: テーマプレビューが見れない問題を修正 +- Fix: ショートカットキーが連打できる問題を修正 + (Cherry-picked from https://github.com/taiyme/misskey/pull/234) +- Fix: MkSignin.vueのcredentialRequestからReactivityを削除(ProxyがPasskey認証処理に渡ることを避けるため) +- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正 + (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/574) +- Fix: Twitchの埋め込みが開けない問題を修正 +- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正 +- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正 +- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正 +- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正 + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672) +- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正 +- Fix: deck uiの通知音が重なる問題 (#14029) +- Fix: ダイレクト投稿の"削除して編集"において、宛先が保持されていなかった問題を修正 +- Fix: 投稿フォームへのURL貼り付けによる引用が下書きに保存されていなかった問題を修正 +- Fix: "削除して編集"や下書きにおいて、リアクションの受け入れ設定が保持/保存されていなかった問題を修正 +- Fix: 照会に `#` から始まる文字列を入力してそのハッシュタグのページを表示する際、入力が `#` のみの場合に「指定されたURLに該当するページはありませんでした。」が表示されてしまう問題を修正 +- Fix: 照会に `@` から始まる文字列を入力してユーザーを照会する際、入力が `@` のみの場合に「問題が発生しました」が表示されてしまう問題を修正 +- Fix: 投稿フォームにノートのURLを貼り付けて"引用として添付"した場合、投稿文を空にすることによるRenote化が出来なかった問題を修正 +- Fix: フォロー中のユーザーに関する"TLに他の人への返信を含める"の設定が分かりづらい問題を修正 +- Fix: タイムラインページを開いた時、`TLに他の人への返信を含める`がオフのときに`ファイル付きのみ`をオンにできない問題を修正 +- Fix: deck uiでタイムラインを切り替えた際にTLの設定項目が更新されず、`TLに他の人への返信を含める`のトグルが表示されない問題を修正 +- Fix: ウィジェットのタイムライン選択欄に無効化されたタイムラインが表示される問題を修正 +- Fix: サウンドにドライブの音声を使用している際にドライブの音声が再生できなくなると設定が変更できなくなる問題を修正 ### Server -- チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 - Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949) -- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006) -- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036) - Enhance: エンドポイント`clips/update`の必須項目を`clipId`のみに - Enhance: エンドポイント`admin/roles/update`の必須項目を`roleId`のみに - Enhance: エンドポイント`pages/update`の必須項目を`pageId`のみに - Enhance: エンドポイント`gallery/posts/update`の必須項目を`postId`のみに - Enhance: エンドポイント`i/webhook/update`の必須項目を`webhookId`のみに - Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに +- Enhance: `default.yml`内の`url`, `db.db`, `db.user`, `db.pass`を環境変数から読み込めるように +- Enhance: エンドポイント`api/meta`にプロパティ`noteSearchableScope`が増え、`string`値`local`または`global`を返却します +- Fix: チャート生成時にinstance.suspensionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 +- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006) +- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036) - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 - Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正 - Fix: 空文字列のリアクションはフォールバックされるように - Fix: リノートにリアクションできないように +- Fix: ユーザー名の前後に空白文字列がある場合は省略するように +- Fix: プロフィール編集時に名前を空白文字列のみにできる問題を修正 +- Fix: ユーザ名のサジェスト時に表示される内容と順番を調整(以下の順番になります) #14149 + 1. フォロー中かつアクティブなユーザ + 2. フォロー中かつ非アクティブなユーザ + 3. フォローしていないアクティブなユーザ + 4. フォローしていない非アクティブなユーザ + + また、自分自身のアカウントもサジェストされるようになりました。 +- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正 + (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652) +- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正 +- Fix: FTT有効時にリモートユーザーのノートがHTLにキャッシュされる問題を修正 +- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正 +- Fix: エラーメッセージの誤字を修正 (#14213) +- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正 +- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正 + (Cherry-picked from https://github.com/Type4ny-Project/Type4ny/commit/e9601029b52e0ad43d9131b555b614e56c84ebc1) +- Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 #14251 +- Fix: `users/search`において `@` から始まる文字列が与えられた際の処理が正しくなかった問題を修正 + - 名前や自己紹介に `@` から始まる文言が含まれるユーザーも検索できるようになります +- Fix: 一部のMisskey以外のソフトウェアからファイルを受け取れない問題 + (Cherry-picked from https://github.com/Secineralyr/misskey.dream/pull/73/commits/652eaff1e8aa00b890d71d2e1e52c263c1e67c76) + - NOTE: `drive_file`の`url`, `uri`, `src`の上限が512から1024に変更されます + Migrationではカラム定義の変更のみが行われます。 + サーバー管理者は各サーバーの必要に応じ`drive_file` `("uri")`に対するインデックスを張りなおすことでより安定しDBの探索が行われる可能性があります。詳細 は [GitHub](https://github.com/misskey-dev/misskey/pull/14323#issuecomment-2257562228)で確認可能です +- Fix: 自分のフォロワー限定投稿に対するリプライがホームタイムラインで見えないことが有る問題を修正 +- Fix: フォローしていないユーザによるフォロワー限定投稿に対するリプライがソーシャルタイムラインで表示されることがある問題を修正 + +### Misskey.js +- Feat: `/drive/files/create` のリクエストに対応(`multipart/form-data`に対応) +- Feat: `/admin/role/create` のロールポリシーの型を修正 ### Misskey.js - Feat: reject時のエラーに型情報を追加 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dcb625626d..3a4dc7b918 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contribution guide We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project. -> **Note** +> [!NOTE] > This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.** > Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\ > The accuracy of machine translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language. @@ -17,16 +17,31 @@ Before creating an issue, please check the following: - Issues should only be used to feature requests, suggestions, and bug tracking. - Please ask questions or troubleshooting in [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3). -> **Warning** +> [!WARNING] > Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged. -## Before implementation +### Recommended discussing before implementation +We welcome your proposal. + When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the PR will not be merged even if it is implemented. At this point, you also need to clarify the goals of the PR you will create, and make sure that the other members of the team are aware of them. PRs that do not have a clear set of do's and don'ts tend to be bloated and difficult to review. -Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask another member to assign you). By expressing your intention to work the Issue, you can prevent conflicts in the work. +Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask Committer to assign you). +By expressing your intention to work on the Issue, you can prevent conflicts in the work. + +To the Committers: you should not assign someone on it before the Final Decision. + +### How issues are triaged + +The Committers may: +* close an issue that is not reproducible on latest stable release, +* merge an issue into another issue, +* split an issue into multiple issues, +* or re-open that has been closed for some reason which is not applicable anymore. + +@syuilo reserves the Final Decision rights including whether the project will implement feature and how to implement, these rights are not always exercised. ## Well-known branches - **`master`** branch is tracking the latest release and used for production purposes. @@ -37,14 +52,14 @@ Also, when you start implementation, assign yourself to the Issue (if you cannot ## Creating a PR Thank you for your PR! Before creating a PR, please check the following: - If possible, prefix the title with a keyword that identifies the type of this PR, as shown below. - - `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc - - Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR. + - `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc + - Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR. - If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text. - Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring. - Check if there are any documents that need to be created or updated due to this change. - If you have added a feature or fixed a bug, please add a test case if possible. - Please make sure that tests and Lint are passed in advance. - - You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing) + - You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing) - If this PR includes UI changes, please attach a screenshot in the text. Thanks for your cooperation 🤗 @@ -54,8 +69,8 @@ Be willing to comment on the good points and not just the things you want fixed ### Review perspective - Scope - - Are the goals of the PR clear? - - Is the granularity of the PR appropriate? + - Are the goals of the PR clear? + - Is the granularity of the PR appropriate? - Security - Does merging this PR create a vulnerability? - Performance @@ -77,7 +92,7 @@ An actual domain will be assigned so you can test the federation. ## Release ### Release Instructions -1. Commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) +1. Commit version changes in the `develop` branch ([package.json](package.json)) 2. Create a release PR. - Into `master` from `develop` branch. - The title must be in the format `Release: x.y.z`. @@ -88,7 +103,7 @@ An actual domain will be assigned so you can test the federation. - The target branch must be `master` - The tag name must be the version -> **Note** +> [!NOTE] > Why this instruction is necessary: > - To perform final QA checks > - To distribute responsibility @@ -106,12 +121,42 @@ If your language is not listed in Crowdin, please open an issue. ![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg) ## Development -During development, it is useful to use the +### Setup +Before developing, you have to set up environment. Misskey requires Redis, PostgreSQL, and FFmpeg. +You would want to install Meilisearch to experiment related features. Technically, meilisearch is not strict requirement, but some features and tests require it. + +There are a few ways to proceed. + +#### Use system-wide software +You could install them in system-wide (such as from package manager). + +#### Use `docker compose` +You could obtain middleware container by typing `docker compose -f $PROJECT_ROOT/compose.local-db.yml up -d`. + +#### Use Devcontainer +Devcontainer also has necessary setting. This method can be done by connecting from VSCode. + +Instead of running `pnpm` locally, you can use Dev Container to set up your development environment. +To use Dev Container, open the project directory on VSCode with Dev Containers installed. +**Note:** If you are using Windows, please clone the repository with WSL. Using Git for Windows will result in broken files due to the difference in how newlines are handled. + +It will run the following command automatically inside the container. +``` bash +git submodule update --init +pnpm install --frozen-lockfile +cp .devcontainer/devcontainer.yml .config/default.yml +pnpm build +pnpm migrate +``` + +After finishing the migration, you can proceed. + +### Start developing +During development, it is useful to use the ``` pnpm dev ``` - command. - Server-side source files and automatically builds them if they are modified. Automatically start the server process(es). @@ -135,26 +180,6 @@ MK_DEV_PREFER=backend pnpm dev - To change the port of Vite, specify with `VITE_PORT` environment variable. - HMR may not work in some environments such as Windows. -### Dev Container -Instead of running `pnpm` locally, you can use Dev Container to set up your development environment. -To use Dev Container, open the project directory on VSCode with Dev Containers installed. -**Note:** If you are using Windows, please clone the repository with WSL. Using Git for Windows will result in broken files due to the difference in how newlines are handled. - -It will run the following command automatically inside the container. -``` bash -git submodule update --init -pnpm install --frozen-lockfile -cp .devcontainer/devcontainer.yml .config/default.yml -pnpm build -pnpm migrate -``` - -After finishing the migration, run the `pnpm dev` command to start the development server. - -``` bash -pnpm dev -``` - ## Testing - Test codes are located in [`/packages/backend/test`](/packages/backend/test). @@ -165,7 +190,7 @@ cp .github/misskey/test.yml .config/ ``` Prepare DB/Redis for testing. ``` -docker compose -f packages/backend/test/docker-compose.yml up +docker compose -f packages/backend/test/compose.yml up ``` Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`. @@ -204,7 +229,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド ### ルート定義 ルート定義は、以下の形式のオブジェクトの配列です。 -``` ts +```ts { name?: string; path: string; @@ -217,7 +242,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド } ``` -> **Warning** +> [!WARNING] > 現状、ルートは定義された順に評価されます。 > たとえば、`/foo/:id`ルート定義の次に`/foo/bar`ルート定義がされていた場合、後者がマッチすることはありません。 @@ -279,7 +304,7 @@ export const Default = { parameters: { layout: 'centered', }, -} satisfies StoryObj; +} satisfies StoryObj; ``` If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file. @@ -390,7 +415,7 @@ describe('test', () => { }) .useMocker(... .compile(); - + fooService = app.get(FooService); barService = app.get(BarService) as jest.Mocked; @@ -511,13 +536,13 @@ pnpm dlx typeorm migration:generate -d ormconfig.js -o - 作成されたスクリプトは不必要な変更を含むため除去してください ### JSON SchemaのobjectでanyOfを使うとき -JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。 -バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます) +JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。 +バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます) https://github.com/misskey-dev/misskey/pull/10082 テキストhogeおよびfugaについて、片方を必須としつつ両方の指定もありうる場合: -``` +```ts export const paramDef = { type: 'object', properties: { @@ -547,3 +572,24 @@ marginはそのコンポーネントを使う側が設定する ### indexというファイル名を使うな ESMではディレクトリインポートは廃止されているのと、ディレクトリインポートせずともファイル名が index だと何故か一部のライブラリ?でディレクトリインポートだと見做されてエラーになる + +## CSS Recipe + +### Lighten CSS vars + +``` css +color: hsl(from var(--MI_THEME-accent) h s calc(l + 10)); +``` + +### Darken CSS vars + +``` css +color: hsl(from var(--MI_THEME-accent) h s calc(l - 10)); +``` + +### Add alpha to CSS vars + +``` css +color: color(from var(--MI_THEME-accent) srgb r g b / 0.5); +``` + diff --git a/Dockerfile b/Dockerfile index d6ca6b8cdf..e21b2a31fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax = docker/dockerfile:1.4 -ARG NODE_VERSION=20.12.2-bullseye +ARG NODE_VERSION=20.16.0-bullseye # build assets & compile TypeScript @@ -21,7 +21,9 @@ WORKDIR /misskey COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] COPY --link ["scripts", "./scripts"] COPY --link ["packages/backend/package.json", "./packages/backend/"] +COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"] COPY --link ["packages/frontend/package.json", "./packages/frontend/"] +COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"] COPY --link ["packages/sw/package.json", "./packages/sw/"] COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"] COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"] diff --git a/chart/files/default.yml b/chart/files/default.yml index f98b8ebfee..4d17131c25 100644 --- a/chart/files/default.yml +++ b/chart/files/default.yml @@ -124,6 +124,14 @@ redis: # #prefix: example-prefix # #db: 1 +#redisForReactions: +# host: redis +# port: 6379 +# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 +# #pass: example-pass +# #prefix: example-prefix +# #db: 1 + # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── diff --git a/docker-compose.local-db.yml b/compose.local-db.yml similarity index 98% rename from docker-compose.local-db.yml rename to compose.local-db.yml index 16ba4b49e1..3835cb23db 100644 --- a/docker-compose.local-db.yml +++ b/compose.local-db.yml @@ -1,5 +1,3 @@ -version: "3" - # このconfigは、 dockerでMisskey本体を起動せず、 redisとpostgresql などだけを起動します services: diff --git a/docker-compose_example.yml b/compose_example.yml similarity index 97% rename from docker-compose_example.yml rename to compose_example.yml index 5cebbe4164..336bd814a7 100644 --- a/docker-compose_example.yml +++ b/compose_example.yml @@ -1,5 +1,3 @@ -version: "3" - services: web: build: . @@ -19,6 +17,8 @@ services: networks: - internal_network - external_network + # env_file: + # - .config/docker.env volumes: - ./files:/misskey/files - ./.config:/misskey/.config:ro diff --git a/cypress/e2e/basic.cy.ts b/cypress/e2e/basic.cy.ts index d2525e0a7d..d2efbf709c 100644 --- a/cypress/e2e/basic.cy.ts +++ b/cypress/e2e/basic.cy.ts @@ -23,6 +23,7 @@ describe('Before setup instance', () => { cy.intercept('POST', '/api/admin/accounts/create').as('signup'); + cy.get('[data-cy-admin-initial-password] input').type('example_password_please_change_this_or_you_will_get_hacked'); cy.get('[data-cy-admin-username] input').type('admin'); cy.get('[data-cy-admin-password] input').type('admin1234'); cy.get('[data-cy-admin-ok]').click(); @@ -119,11 +120,16 @@ describe('After user signup', () => { it('signin', () => { cy.visitHome(); - cy.intercept('POST', '/api/signin').as('signin'); + cy.intercept('POST', '/api/signin-flow').as('signin'); cy.get('[data-cy-signin]').click(); - cy.get('[data-cy-signin-username] input').type('alice'); - // Enterキーでサインインできるかの確認も兼ねる + + cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); + // Enterキーで続行できるかの確認も兼ねる + cy.get('[data-cy-signin-username] input').type('alice{enter}'); + + cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 }); + // Enterキーで続行できるかの確認も兼ねる cy.get('[data-cy-signin-password] input').type('alice1234{enter}'); cy.wait('@signin'); @@ -138,8 +144,9 @@ describe('After user signup', () => { cy.visitHome(); cy.get('[data-cy-signin]').click(); - cy.get('[data-cy-signin-username] input').type('alice'); - cy.get('[data-cy-signin-password] input').type('alice1234{enter}'); + + cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); + cy.get('[data-cy-signin-username] input').type('alice{enter}'); // TODO: cypressにブラウザの言語指定できる機能が実装され次第英語のみテストするようにする cy.contains(/アカウントが凍結されています|This account has been suspended due to/gi); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 281f2e6ccd..197ff963ac 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -48,16 +48,19 @@ Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => { cy.request('POST', route, { username: username, password: password, + ...(isAdmin ? { setupPassword: 'example_password_please_change_this_or_you_will_get_hacked' } : {}), }).its('body').as(username); }); Cypress.Commands.add('login', (username, password) => { cy.visitHome(); - cy.intercept('POST', '/api/signin').as('signin'); + cy.intercept('POST', '/api/signin-flow').as('signin'); cy.get('[data-cy-signin]').click(); - cy.get('[data-cy-signin-username] input').type(username); + cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); + cy.get('[data-cy-signin-username] input').type(`${username}{enter}`); + cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 }); cy.get('[data-cy-signin-password] input').type(`${password}{enter}`); cy.wait('@signin').as('signedIn'); diff --git a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts b/idea/MkAbuseReport.stories.impl.ts similarity index 88% rename from packages/frontend/src/components/MkAbuseReport.stories.impl.ts rename to idea/MkAbuseReport.stories.impl.ts index cf09c96fd4..717bceb23d 100644 --- a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts +++ b/idea/MkAbuseReport.stories.impl.ts @@ -7,8 +7,8 @@ import { action } from '@storybook/addon-actions'; import { StoryObj } from '@storybook/vue3'; import { HttpResponse, http } from 'msw'; -import { abuseUserReport } from '../../.storybook/fakes.js'; -import { commonHandlers } from '../../.storybook/mocks.js'; +import { abuseUserReport } from '../packages/frontend/.storybook/fakes.js'; +import { commonHandlers } from '../packages/frontend/.storybook/mocks.js'; import MkAbuseReport from './MkAbuseReport.vue'; export const Default = { render(args) { diff --git a/idea/MkDisableSection.vue b/idea/MkDisableSection.vue new file mode 100644 index 0000000000..360705071b --- /dev/null +++ b/idea/MkDisableSection.vue @@ -0,0 +1,41 @@ + + + + + + + diff --git a/idea/README.md b/idea/README.md new file mode 100644 index 0000000000..f64d16800a --- /dev/null +++ b/idea/README.md @@ -0,0 +1 @@ +使われなくなったけど消すのは勿体ない(将来使えるかもしれない)コードを入れておくとこ diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 955d672c1d..de24ad4bb9 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -626,10 +626,7 @@ abuseReported: "أُرسل البلاغ، شكرًا لك" reporter: "المُبلّغ" reporteeOrigin: "أصل البلاغ" reporterOrigin: "أصل المُبلّغ" -forwardReport: "وجّه البلاغ إلى المثيل البعيد" -forwardReportIsAnonymous: "في المثيل البعيد سيظهر المبلّغ كحساب مجهول." send: "أرسل" -abuseMarkAsResolved: "علّم البلاغ كمحلول" openInNewTab: "افتح في لسان جديد" defaultNavigationBehaviour: "سلوك الملاحة الافتراضي" editTheseSettingsMayBreakAccount: "تعديل هذه الإعدادات قد يسبب عطبًا لحسابك" @@ -1255,15 +1252,12 @@ _theme: buttonBg: "خلفية الأزرار" buttonHoverBg: "خلفية الأزرار (عند التمرير فوقها)" inputBorder: "حواف حقل الإدخال" - listItemHoverBg: "خلفية عناصر القائمة (عند التمرير فوقها)" driveFolderBg: "خلفية مجلد قرص التخزين" messageBg: "خلفية المحادثة" _sfx: note: "الملاحظات" noteMy: "ملاحظتي" notification: "الإشعارات" - antenna: "الهوائيات" - channel: "إشعارات القنات" _ago: future: "المستقبَل" justNow: "اللحظة" @@ -1535,6 +1529,7 @@ _notification: reaction: "التفاعل" receiveFollowRequest: "طلبات المتابعة" followRequestAccepted: "طلبات المتابعة المقبولة" + login: "لِج" app: "إشعارات التطبيقات المرتبطة" _actions: followBack: "تابعك بالمثل" @@ -1566,6 +1561,10 @@ _webhookSettings: active: "مُفعّل" _events: reaction: "عند التفاعل" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "البريد الإلكتروني " _moderationLogTypes: suspend: "علِق" deleteDriveFile: "حُذف الملف" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index abcf07da83..0e761b0743 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -451,7 +451,6 @@ or: "অথবা" language: "ভাষা" uiLanguage: "UI এর ভাষা" aboutX: "{x} সম্পর্কে" -disableDrawer: "ড্রয়ার মেনু প্রদর্শন করবেন না" noHistory: "কোনো ইতিহাস নেই" signinHistory: "প্রবেশ করার ইতিহাস" doing: "প্রক্রিয়া করছে..." @@ -625,10 +624,7 @@ abuseReported: "আপনার অভিযোগটি দাখিল কর reporter: "অভিযোগকারী" reporteeOrigin: "অভিযোগটির উৎস" reporterOrigin: "অভিযোগকারীর উৎস" -forwardReport: "রিমোট ইন্সত্যান্সে অভিযোগটি পাঠান" -forwardReportIsAnonymous: "আপনার তথ্য রিমোট ইন্সত্যান্সে পাঠানো হবে না এবং একটি বেনামী সিস্টেম অ্যাকাউন্ট হিসাবে প্রদর্শিত হবে।" send: "পাঠান" -abuseMarkAsResolved: "অভিযোগটিকে সমাধাকৃত হিসাবে চিহ্নিত করুন" openInNewTab: "নতুন ট্যাবে খুলুন" openInSideView: "সাইড ভিউতে খুলুন" defaultNavigationBehaviour: "ডিফল্ট নেভিগেশন" @@ -1021,7 +1017,6 @@ _theme: buttonBg: "বাটনের পটভূমি" buttonHoverBg: "বাটনের পটভূমি (হভার)" inputBorder: "ইনপুট ফিল্ডের বর্ডার" - listItemHoverBg: "লিস্ট আইটেমের পটভূমি (হোভার)" driveFolderBg: "ড্রাইভ ফোল্ডারের পটভূমি" wallpaperOverlay: "ওয়ালপেপার ওভারলে" badge: "ব্যাজ" @@ -1033,8 +1028,6 @@ _sfx: note: "নোটগুলি" noteMy: "নোট (আপনার)" notification: "বিজ্ঞপ্তি" - antenna: "অ্যান্টেনাগুলি" - channel: "চ্যানেলের বিজ্ঞপ্তি" _ago: future: "ভবিষ্যৎ" justNow: "এইমাত্র" @@ -1316,6 +1309,7 @@ _notification: pollEnded: "পোল শেষ" receiveFollowRequest: "প্রাপ্ত অনুসরণের অনুরোধসমূহ" followRequestAccepted: "গৃহীত অনুসরণের অনুরোধসমূহ" + login: "প্রবেশ করুন" app: "লিঙ্ক করা অ্যাপ থেকে বিজ্ঞপ্তি" _actions: followBack: "ফলো ব্যাক করেছে" @@ -1346,6 +1340,10 @@ _deck: _webhookSettings: name: "নাম" active: "চালু" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "ইমেইল" _moderationLogTypes: suspend: "স্থগিত করা" resetPassword: "পাসওয়ার্ড রিসেট করুন" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 0345ee0326..7b668e5ce9 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -8,6 +8,8 @@ search: "Cercar" notifications: "Notificacions" username: "Nom d'usuari" password: "Contrasenya" +initialPasswordForSetup: "Contrasenya inicial per la configuració inicial" +initialPasswordIsIncorrect: "La contrasenya no és correcta." forgotPassword: "Contrasenya oblidada" fetchingAsApObject: "Cercant en el Fediverse..." ok: "OK" @@ -60,6 +62,7 @@ copyFileId: "Copiar ID d'arxiu" copyFolderId: "Copiar ID de carpeta" copyProfileUrl: "Copiar URL del perfil" searchUser: "Cercar un usuari" +searchThisUsersNotes: "Cerca les publicacions de l'usuari" reply: "Respondre" loadMore: "Carregar més" showMore: "Veure més" @@ -108,11 +111,14 @@ enterEmoji: "Introduir un emoji" renote: "Impulsa" unrenote: "Anul·la l'impuls" renoted: "S'ha impulsat" +renotedToX: "Impulsat per {name}." cantRenote: "No es pot impulsar aquesta publicació" cantReRenote: "No es pot impulsar l'impuls." quote: "Cita" inChannelRenote: "Renotar només al Canal" inChannelQuote: "Citar només al Canal" +renoteToChannel: "Impulsa a un canal" +renoteToOtherChannel: "Impulsa a un altre canal" pinnedNote: "Nota fixada" pinned: "Fixar al perfil" you: "Tu" @@ -151,6 +157,7 @@ editList: "Editar llista" selectChannel: "Selecciona un canal" selectAntenna: "Tria una antena" editAntenna: "Modificar antena" +createAntenna: "Crea una antena" selectWidget: "Triar un giny" editWidgets: "Editar ginys" editWidgetsExit: "Fet" @@ -177,6 +184,10 @@ addAccount: "Afegeix un compte" reloadAccountsList: "Recarregar la llista de contactes" loginFailed: "S'ha produït un error al accedir." showOnRemote: "Navega més en el perfil original" +continueOnRemote: "Veure perfil original" +chooseServerOnMisskeyHub: "Escull un servidor des del Hub de Misskey" +specifyServerHost: "Especifica un servidor directament" +inputHostName: "Introdueix el domini" general: "General" wallpaper: "Fons de Pantalla" setWallpaper: "Defineix el fons de pantalla" @@ -187,6 +198,7 @@ followConfirm: "Estàs segur que vols deixar de seguir {name}?" proxyAccount: "Compte de proxy" proxyAccountDescription: "Un compte proxy és un compte que actua com a seguidor remot per als usuaris en determinades condicions. Per exemple, quan un usuari afegeix un usuari remot a la llista, l'activitat de l'usuari remot no es lliurarà al servidor si cap usuari local segueix aquest usuari, de manera que el compte proxy el seguirà." host: "Amfitrió" +selectSelf: "Escollir manualment" selectUser: "Selecciona usuari/a" recipient: "Destinatari" annotation: "Comentaris" @@ -202,6 +214,7 @@ perDay: "Per dia" stopActivityDelivery: "Deixa d'enviar activitats" blockThisInstance: "Deixa d'enviar activitats" silenceThisInstance: "Silencia aquesta instància " +mediaSilenceThisInstance: "Silenciar els arxius d'aquesta instància " operations: "Accions" software: "Programari" version: "Versió" @@ -223,6 +236,10 @@ blockedInstances: "Instàncies bloquejades" blockedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols bloquejar separades per un salt de pàgina. Les instàncies llistades no podran comunicar-se amb aquesta instància." silencedInstances: "Instàncies silenciades" silencedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols silenciar. Tots els comptes de les instàncies llistades s'establiran com silenciades i només podran fer sol·licitacions de seguiment, i no podran mencionar als comptes locals si no els segueixen. Això no afectarà les instàncies bloquejades." +mediaSilencedInstances: "Instàncies amb els arxius silenciats" +mediaSilencedInstancesDescription: "Llista els noms dels servidors que vulguis silenciar els arxius, un servidor per línia. Tots els comptes que pertanyin als servidors llistats seran tractats com sensibles i no podran fer servir emojis personalitzats. Això no tindrà efecte sobre els servidors blocats." +federationAllowedHosts: "Llista de servidors federats" +federationAllowedHostsDescription: "Llista dels servidors amb els quals es federa." muteAndBlock: "Silencia i bloca" mutedUsers: "Usuaris silenciats" blockedUsers: "Usuaris bloquejats" @@ -313,6 +330,7 @@ selectFile: "Selecciona fitxers" selectFiles: "Selecciona fitxers" selectFolder: "Selecció de carpeta" selectFolders: "Selecció de carpeta" +fileNotSelected: "Cap fitxer seleccionat" renameFile: "Canvia el nom del fitxer" folderName: "Nom de la carpeta" createFolder: "Crea una carpeta" @@ -320,6 +338,7 @@ renameFolder: "Canvia el nom de la carpeta" deleteFolder: "Elimina la carpeta" folder: "Carpeta " addFile: "Afegeix un fitxer" +showFile: "Mostrar fitxer" emptyDrive: "La teva unitat és buida" emptyFolder: "La carpeta està buida" unableToDelete: "No es pot eliminar" @@ -434,6 +453,7 @@ totpDescription: "Escriu una contrasenya d'un sol us fent servir l'aplicació d' moderator: "Moderador/a" moderation: "Moderació" moderationNote: "Nota de moderació " +moderationNoteDescription: "Pots escriure notes que es compartiran entre els moderadors." addModerationNote: "Afegir una nota de moderació " moderationLogs: "Registre de moderació " nUsersMentioned: "{n} usuaris mencionats" @@ -468,10 +488,12 @@ retype: "Torneu a introduir-la" noteOf: "Publicació de: {user}" quoteAttached: "Frase adjunta" quoteQuestion: "Vols annexar-la com a cita?" +attachAsFileQuestion: "El text copiat és massa llarg. Vols adjuntar-lo com un fitxer de text?" noMessagesYet: "Encara no hi ha missatges" newMessageExists: "Has rebut un nou missatge" onlyOneFileCanBeAttached: "Només pots adjuntar un fitxer a un missatge" signinRequired: "Si us plau, Registra't o inicia la sessió abans de continuar" +signinOrContinueOnRemote: "Per continuar necessites moure el teu servidor o registrar-te / iniciar sessió en aquest servidor." invitations: "Convida" invitationCode: "Codi d'invitació" checking: "Comprovació en curs..." @@ -493,7 +515,10 @@ uiLanguage: "Idioma de l'interfície" aboutX: "Respecte a {x}" emojiStyle: "Estil d'emoji" native: "Nadiu" -disableDrawer: "No mostrar els menús en calaixos" +menuStyle: "Estil de menú" +style: "Estil" +drawer: "Calaix" +popup: "Emergent" showNoteActionsOnlyHover: "Només mostra accions de la nota en passar amb el cursor" showReactionsCount: "Mostra el nombre de reaccions a les publicacions" noHistory: "No hi ha un registre previ" @@ -543,7 +568,7 @@ objectStorageUseSSLDesc: "Desactiva'l si no tens pensat fer servir HTTPS per les objectStorageUseProxy: "Connectar-se mitjançant un Proxy" objectStorageUseProxyDesc: "Desactiva'l si no faràs servir un Proxy per les connexions de l'API" objectStorageSetPublicRead: "Configurar les pujades com públiques " -s3ForcePathStyleDesc: "Si s3ForcePathStyle es troba activat el nom del dipòsit s'ha d'incloure a l'adreça URL en comtes del nom del host. Potser que necessitis activar-ho quan facis servir, per exemple, Minio a un servidor propi." +s3ForcePathStyleDesc: "Si s3ForcePathStyle es troba activat el nom del cubell s'haurà d'especificar com a part de l'adreça URL en comptes del nom del servidor. Podria ser que necessitis activar aquesta opció quan facis servir serveis com ara l'allotjament a un servidor propi." serverLogs: "Registres del servidor" deleteAll: "Elimina-ho tot" showFixedPostForm: "Mostrar el formulari per escriure a l'inici de la línia de temps" @@ -576,6 +601,8 @@ ascendingOrder: "Ascendent" descendingOrder: "Descendent" scratchpad: "Bloc de proves" scratchpadDescription: "El bloc de proves proporciona un entorn experimental per AiScript. Pot escriure i verificar els resultats que interactuen amb Misskey." +uiInspector: "Inspector de la interfície" +uiInspectorDescription: "Podeu visualitzar una llista d'elements UI presents en la memòria. Els components de la interfície d'usuari són generats per les funcions Ui:C:." output: "Sortida" script: "Script" disablePagesScript: "Desactivar AiScript a les pàgines " @@ -692,10 +719,7 @@ abuseReported: "La teva denúncia s'ha enviat. Moltes gràcies." reporter: "Denunciant " reporteeOrigin: "Origen de la denúncia " reporterOrigin: "Origen del denunciant" -forwardReport: "Transferir la denúncia a una instància remota" -forwardReportIsAnonymous: "En lloc del teu compte, es farà servir un compte anònim com a denunciant al servidor remot." send: "Envia" -abuseMarkAsResolved: "Marca la denúncia com a resolta" openInNewTab: "Obre a una pestanya nova" openInSideView: "Obre a una vista lateral" defaultNavigationBehaviour: "Navegació per defecte" @@ -832,6 +856,7 @@ administration: "Administració" accounts: "Comptes" switch: "Canvia" noMaintainerInformationWarning: "La informació de l'administrador no s'ha configurat" +noInquiryUrlWarning: "No s'ha desat l'URL de consulta." noBotProtectionWarning: "La protecció contra bots no s'ha configurat." configure: "Configurar" postToGallery: "Crear una nova publicació a la galeria" @@ -896,6 +921,7 @@ followersVisibility: "Visibilitat dels seguidors" continueThread: "Veure la continuació del fil" deleteAccountConfirm: "Això eliminarà el teu compte irreversiblement. Procedir?" incorrectPassword: "Contrasenya incorrecta." +incorrectTotp: "La contrasenya no és correcta, o ha caducat." voteConfirm: "Confirma el teu vot \"{choice}\"" hide: "Amagar" useDrawerReactionPickerForMobile: "Mostrar el selector de reaccions com un calaix al mòbil " @@ -1021,6 +1047,7 @@ thisPostMayBeAnnoyingHome: "Publicar a la línia de temps d'Inici" thisPostMayBeAnnoyingCancel: "Cancel·lar " thisPostMayBeAnnoyingIgnore: "Publicar de totes maneres" collapseRenotes: "Col·lapsar les renotes que ja has vist" +collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has renotat" internalServerError: "Error intern del servidor" internalServerErrorDescription: "El servidor ha fallat de manera inexplicable." copyErrorInfo: "Copiar la informació de l'error " @@ -1094,6 +1121,8 @@ preservedUsernames: "Noms d'usuaris reservats" preservedUsernamesDescription: "Llistat de noms d'usuaris que no es poden fer servir separats per salts de linia. Aquests noms d'usuaris no estaran disponibles quan es creï un compte d'usuari normal, però els administradors els poden fer servir per crear comptes manualment. Per altre banda els comptes ja creats amb aquests noms d'usuari no es veure'n afectats." createNoteFromTheFile: "Compon una nota des d'aquest fitxer" archive: "Arxiu" +archived: "Arxivat" +unarchive: "Desarxivar" channelArchiveConfirmTitle: "Vols arxivar {name}?" channelArchiveConfirmDescription: "Un Canal arxivat no apareixerà a la llista de canals o als resultats de cerca. Tampoc es poden afegir noves entrades." thisChannelArchived: "Aquest Canal ha sigut arxivat." @@ -1104,6 +1133,9 @@ preventAiLearning: "Descartar l'ús d'aprenentatge automàtic (IA Generativa)" preventAiLearningDescription: "Demanar els indexadors no fer servir els texts, imatges, etc. en cap conjunt de dades per alimentar l'aprenentatge automàtic (IA Predictiva/ Generativa). Això s'aconsegueix afegint la etiqueta \"noai\" com a resposta HTML al contingut corresponent. Prevenir aquest ús totalment pot ser que no sigui aconseguit, ja que molts indexadors poden obviar aquesta etiqueta." options: "Opcions" specifyUser: "Especificar usuari" +lookupConfirm: "Vols fer una cerca?" +openTagPageConfirm: "Vols obrir una pàgina d'etiquetes?" +specifyHost: "Especifica un servidor" failedToPreviewUrl: "Vista prèvia no disponible" update: "Actualitzar" rolesThatCanBeUsedThisEmojiAsReaction: "Rols que poden fer servir aquest emoji com a reacció " @@ -1172,7 +1204,10 @@ confirmShowRepliesAll: "Aquesta opció no té marxa enrere. Vols mostrar les tev confirmHideRepliesAll: "Aquesta opció no té marxa enrere. Vols ocultar les teves respostes a tots els usuaris que segueixes a la línia de temps?" externalServices: "Serveis externs" sourceCode: "Codi font" +sourceCodeIsNotYetProvided: "El codi font encara no es troba disponible. Contacta amb l'administrador per solucionar aquest problema." repositoryUrl: "URL del repositori" +repositoryUrlDescription: "Si estàs fent servir Misskey tal com és (sense cap canvi al codi font), introdueix https://github.com/misskey-dev/misskey" +repositoryUrlOrTarballRequired: "Si no ofereixes cap repositori, publica un fitxer tarball. Dona una ullada a .config/example.yml per a més informació." feedback: "Opinió" feedbackUrl: "URL per a opinar" impressum: "Impressum" @@ -1211,6 +1246,7 @@ showReplay: "Veure reproducció" replay: "Reproduir" replaying: "Reproduint" endReplay: "Tanca la redifusió" +copyReplayData: "Copia les dades de la resposta" ranking: "Classificació" lastNDays: "Últims {n} dies" backToTitle: "Torna al títol" @@ -1224,12 +1260,59 @@ gameRetry: "Torna a provar" notUsePleaseLeaveBlank: "Si no voleu usar-ho, deixeu-ho en blanc" useTotp: "Usa una contrasenya d'un sol ús" useBackupCode: "Usa un codi de recuperació" +launchApp: "Inicia l'aplicació " +useNativeUIForVideoAudioPlayer: "Fes servir la UI del navegador quan reprodueixis vídeo i àudio " +keepOriginalFilename: "Desa el nom del fitxer original" +keepOriginalFilenameDescription: "Si desactives aquesta opció els noms dels fitxers se substituiran per una cadena aleatòria quan carreguis nous fitxers de forma automàtica." +noDescription: "No hi ha una descripció " +alwaysConfirmFollow: "Confirma sempre els seguiments" +inquiry: "Contacte" +tryAgain: "Intenta-ho més tard." +confirmWhenRevealingSensitiveMedia: "Confirmació quan revelis contingut sensible " +sensitiveMediaRevealConfirm: "Aquest contingut potser sensible. Segur que ho vols revelar?" +createdLists: "Llistes creades " +createdAntennas: "Antenes creades" +fromX: "De {x}" +genEmbedCode: "Obtenir el codi per incrustar" +noteOfThisUser: "Notes d'aquest usuari" +clipNoteLimitExceeded: "No es poden afegir més notes a aquest clip." +performance: "Rendiment" +modified: "Modificat" +discard: "Descarta" +thereAreNChanges: "Hi ha(n) {n} canvi(s)" +signinWithPasskey: "Inicia sessió amb Passkey" +unknownWebAuthnKey: "Passkey desconeguda" +passkeyVerificationFailed: "La verificació a fallat" +passkeyVerificationSucceededButPasswordlessLoginDisabled: "La verificació de la passkey a estat correcta, però s'ha deshabilitat l'inici de sessió sense contrasenya." +messageToFollower: "Missatge als meus seguidors" +target: "Assumpte " +_abuseUserReport: + forward: "Reenviar " + forwardDescription: "Reenvia l'informe a una altra instància com un compte del sistema anònima." + resolve: "Solució " + accept: "Acceptar " + reject: "Rebutjar" + resolveTutorial: "Si l'informe és legítim selecciona \"Acceptar\" per resoldre'l positivament. Però si l'informe no és legítim selecciona \"Rebutjar\" per resoldre'l negativament." _delivery: + status: "Estat d'entrega " stop: "Suspés" + resume: "Torna a enviar" _type: none: "S'està publicant" + manuallySuspended: "Suspendre manualment" + goneSuspended: "Servidor suspès perquè el servidor s'ha esborrat" + autoSuspendedForNotResponding: "Servidor suspès perquè el servidor no respon" _bubbleGame: howToPlay: "Com es juga" + hold: "Mantenir" + _score: + score: "Puntuació " + scoreYen: "Diners guanyats" + highScore: "Millor puntuació " + maxChain: "Nombre màxim de combos" + yen: "{yen}Ien" + estimatedQty: "{qty}peces" + scoreSweets: "{onigiriQtyWithUnit}ongiris" _howToPlay: section1: "Ajusta la posició i deixa caure l'objecte dintre la caixa." section2: "Quan dos objectes del mateix tipus es toquen, canviaran en un objecte diferent i guanyares punts." @@ -1344,6 +1427,9 @@ _serverSettings: fanoutTimelineDescription: "Quan es troba activat millora bastant el rendiment quan es recuperen les línies de temps i redueix la carrega de la base de dades. Com a contrapunt, l'ús de memòria de Redis es veurà incrementada. Considera d'estabilitat aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes de inestabilitat." fanoutTimelineDbFallback: "Carregar de la base de dades" fanoutTimelineDbFallbackDescription: "Quan s'activa, la línia de temps fa servir la base de dades per consultes adicionals si la línia de temps no es troba a la memòria cau. Si és desactiva la càrrega del servidor és veure reduïda, però també és reduirà el nombre de línies de temps que és poden obtenir." + reactionsBufferingDescription: "Quan s'activa aquesta opció millora bastant el rendiment en recuperar les línies de temps reduint la càrrega de la base. Com a contrapunt, augmentarà l'ús de memòria de Redís. Desactiva aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes d'inestabilitat." + inquiryUrl: "URL de consulta " + inquiryUrlDescription: "Escriu adreça URL per al formulari de consulta per al mantenidor del servidor o una pàgina web amb el contacte d'informació." _accountMigration: moveFrom: "Migrar un altre compte a aquest" moveFromSub: "Crear un àlies per un altre compte" @@ -1651,6 +1737,7 @@ _role: gtlAvailable: "Pot veure la línia de temps global" ltlAvailable: "Pot veure la línia de temps local" canPublicNote: "Pot enviar notes públiques" + mentionMax: "Nombre màxim de mencions a una nota" canInvite: "Pot crear invitacions a la instància " inviteLimit: "Límit d'invitacions " inviteLimitCycle: "Temps de refresc de les invitacions" @@ -1659,6 +1746,7 @@ _role: canManageAvatarDecorations: "Gestiona les decoracions dels avatars " driveCapacity: "Capacitat del disc" alwaysMarkNsfw: "Marca sempre els fitxers com a sensibles" + canUpdateBioMedia: "Permet l'edició d'una icona o un bàner" pinMax: "Nombre màxim de notes fixades" antennaMax: "Nombre màxim d'antenes" wordMuteMax: "Nombre màxim de caràcters permesos a les paraules silenciades" @@ -1673,9 +1761,20 @@ _role: canSearchNotes: "Pot cercar notes" canUseTranslator: "Pot fer servir el traductor" avatarDecorationLimit: "Nombre màxim de decoracions que es poden aplicar els avatars" + canImportAntennas: "Autoritza la importació d'antenes " + canImportBlocking: "Autoritza la importació de bloquejats" + canImportFollowing: "Autoritza la importació de seguidors" + canImportMuting: "Autoritza la importació de silenciats" + canImportUserLists: "Autoritza la importació de llistes d'usuaris " _condition: + roleAssignedTo: "Assignat a rols manuals" isLocal: "Usuari local" isRemote: "Usuari remot" + isCat: "Usuaris gats" + isBot: "Usuaris bots" + isSuspended: "Usuari suspès" + isLocked: "Comptes privats" + isExplorable: "Fes que el compte aparegui a les cerques" createdLessThan: "Han passat menys de X a passat des de la creació del compte" createdMoreThan: "Han passat més de X des de la creació del compte" followersLessThanOrEq: "Té menys de X seguidors" @@ -1745,6 +1844,7 @@ _plugin: installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança." manage: "Gestionar els afegits" viewSource: "Veure l'origen " + viewLog: "Mostra el registre" _preferencesBackups: list: "Llista de còpies de seguretat" saveNew: "Fer una còpia de seguretat nova" @@ -1774,6 +1874,8 @@ _aboutMisskey: contributors: "Col·laboradors principals" allContributors: "Tots els col·laboradors " source: "Codi font" + original: "Original" + thisIsModifiedVersion: "En {name} fa servir una versió modificada de Misskey." translation: "Tradueix Misskey" donate: "Fes un donatiu a Misskey" morePatrons: "També agraïm el suport d'altres col·laboradors que no surten en aquesta llista. Gràcies! 🥰" @@ -1881,7 +1983,6 @@ _theme: buttonBg: "Fons botó " buttonHoverBg: "Fons botó (en passar-hi per sobre)" inputBorder: "Contorn del cap d'introducció " - listItemHoverBg: "Fons dels elements d'una llista" driveFolderBg: "Fons de la carpeta Disc" wallpaperOverlay: "Superposició del fons de pantalla " badge: "Insígnia " @@ -1893,8 +1994,6 @@ _sfx: note: "Notes" noteMy: "Nota (per mi)" notification: "Notificacions" - antenna: "Antenes" - channel: "Notificacions dels canals" reaction: "Quan se selecciona una reacció " _soundSettings: driveFile: "Fer servir un fitxer d'àudio del disc" @@ -1903,6 +2002,7 @@ _soundSettings: driveFileTypeWarnDescription: "Seleccionar un fitxer d'àudio " driveFileDurationWarn: "L'àudio és massa llarg" driveFileDurationWarnDescription: "Els àudios molt llargs pot interrompre l'ús de Misskey. Vols continuar?" + driveFileError: "El so no es pot carregar. Canvia la configuració" _ago: future: "Futur " justNow: "Ara mateix" @@ -1955,6 +2055,7 @@ _2fa: backupCodesDescription: "Si l'aplicació d'autenticació no es pot utilitzar, es pot accedir al compte utilitzant els següents codis de còpia de seguretat. Assegura't de mantenir aquests codis en un lloc segur. Cada codi es pot utilitzar només una vegada." backupCodeUsedWarning: "Es va utilitzar un codi de còpia de seguretat. Si l'aplicació de certificació està disponible, reconfigura l'aplicació d'autenticació tan aviat com sigui possible." backupCodesExhaustedWarning: "Es van utilitzar tots els codis de còpia de seguretat. Si no es pot utilitzar l'aplicació d'autenticació, ja no es pot accedir al compte. Torna a registrar l'aplicació d'autenticació." + moreDetailedGuideHere: "Aquí tens una guia al detall" _permissions: "read:account": "Veure la informació del compte." "write:account": "Editar la informació del compte." @@ -2028,22 +2129,73 @@ _permissions: "read:admin:emoji": "Veure emojis" "write:admin:queue": "Gestionar la cua de feines" "read:admin:queue": "Veure la cua de feines" + "write:admin:promo": "Gestiona les notes promocionals" + "write:admin:drive": "Gestiona el disc de l'usuari" + "read:admin:drive": "Veure la informació del disc de l'usuari" + "read:admin:stream": "Fes servir l'API sobre Websocket per l'administració" + "write:admin:ad": "Gestiona la publicitat" + "read:admin:ad": "Veure anuncis" + "write:invite-codes": "Crear codis d'invitació" + "read:invite-codes": "Obtenir codis d'invitació" + "write:clip-favorite": "Gestionar els clips favorits" + "read:clip-favorite": "Veure clips favorits" + "read:federation": "Veure dades de federació" + "write:report-abuse": "Informar d'un abús" +_auth: + shareAccessTitle: "Concedeix permisos a l'aplicació" + shareAccess: "Vols que {name} pugui accedir al vostre compte?" + shareAccessAsk: "Segur que vols que aquesta aplicació pugui accedir al vostre compte?" + permission: "{name} demana els següents permisos" + permissionAsk: "Aquesta aplicació demana els següents permisos" + pleaseGoBack: "Si us plau, torna a l'aplicació" + callback: "Tornant a l'aplicació" + denied: "Accés denegat" + pleaseLogin: "Si us plau, identificat per autoritzar l'aplicació." _antennaSources: all: "Totes les publicacions" homeTimeline: "Publicacions dels usuaris seguits" users: "Publicacions d'usuaris específics" userList: "Publicacions d'una llista d'usuaris" + userBlacklist: "Totes les notes excepte les d'un o alguns usuaris especificats" +_weekday: + sunday: "Diumenge" + monday: "Dilluns" + tuesday: "Dimarts" + wednesday: "Dimecres" + thursday: "Dijous" + friday: "Divendres" + saturday: "Dissabte" _widgets: profile: "Perfil" instanceInfo: "Informació del fitxer d'instal·lació" + memo: "Notes adhesives" notifications: "Notificacions" timeline: "Línia de temps" + calendar: "Calendari" + trends: "Tendència" + clock: "Rellotge" + rss: "Lector RSS" + rssTicker: "RSS ticker" activity: "Activitat" + photos: "Fotografies" + digitalClock: "Rellotge digital" + unixClock: "Rellotge UNIX" federation: "Federació" + instanceCloud: "Núvol d'instàncies" + postForm: "Formulari de publicació" + slideshow: "Presentació" button: "Botó " + onlineUsers: "Usuaris actius" jobQueue: "Cua de tasques" + serverMetric: "Mètriques del servidor" + aiscript: "Consola AiScript" + aiscriptApp: "Aplicació AiScript" + aichan: "Ai" + userList: "Llistat d'usuaris" _userList: chooseList: "Tria una llista" + clicker: "Clicker" + birthdayFollowings: "Usuaris que fan l'aniversari avui" _cw: hide: "Amagar" show: "Carregar més" @@ -2107,27 +2259,79 @@ _profile: changeBanner: "Canviar el bàner " verifiedLinkDescription: "Escrivint una adreça URL que enllaci a aquest perfil, una icona de propietat verificada es mostrarà al costat del camp." avatarDecorationMax: "Pot afegir un màxim de {max} decoracions." + followedMessage: "Missatge als nous seguidors" + followedMessageDescription: "Es pot configurar un missatge curt que es mostra a l'altra persona quan comença a seguir-te." + followedMessageDescriptionForLockedAccount: "Si comencen a seguir-te es mostra un missatge de quan es permet aquesta sol·licitud. " _exportOrImport: allNotes: "Totes les publicacions" + favoritedNotes: "Notes preferides" clips: "Retalls" followingList: "Seguint" muteList: "Silencia" blockingList: "Bloqueja" userLists: "Llistes" + excludeMutingUsers: "Exclou usuaris silenciats" + excludeInactiveUsers: "Exclou usuaris inactius" + withReplies: "Inclou a la línia de temps les respostes d'usuaris importats" _charts: federation: "Federació" + apRequest: "Peticions" + usersIncDec: "Diferència entre el nombre d'usuaris" + usersTotal: "Nombre total d'usuaris" + activeUsers: "Usuaris actius" + notesIncDec: "Diferència entre el nombre de notes" + localNotesIncDec: "Diferencia en el nombre de notes locals" + remoteNotesIncDec: "Diferencia en el nombre de notes remotes" + notesTotal: "Nombre total de notes" + filesIncDec: "Diferencia en el nombre de fitxers" + filesTotal: "Nombre total de fitxers" + storageUsageIncDec: "Diferencia en l'emmagatzematge usat" + storageUsageTotal: "Emmagatzematge usat" +_instanceCharts: + requests: "Peticions" + users: "Diferència entre el nombre d'usuaris" + usersTotal: "Usuaris totals acumulats" + notes: "Diferència entre el nombre de notes" + notesTotal: "Notes totals acumulades" + ff: "Diferència en nombre d'usuaris seguits / seguidors" + ffTotal: "Nombre total acumulat d'usuaris seguits / seguidors" + cacheSize: "Diferència a la mida de la memòria cau" + cacheSizeTotal: "Total acumulat de la mida de la memòria cau" + files: "Diferència al nombre d'arxius" + filesTotal: "Nombre acumulatiu de fitxers" _timelines: home: "Inici" local: "Local" social: "Social" global: "Global" _play: + new: "Crear un guió" + edit: "Editar guió" + created: "Guió creat" + updated: "Guió editat" + deleted: "Guió esborrat" + pageSetting: "Configuració del guió" + editThisPage: "Edita aquest guió" viewSource: "Veure l'origen " + my: "Els meus guions" + liked: "Guions que m'han agradat" featured: "Popular" title: "Títol " script: "Script" summary: "Descripció" + visibilityDescription: "" _pages: + newPage: "pa" + editPage: "Editar la pàgina" + readPage: "Veure el codi font d'aquesta pàgina" + created: "La pàgina ha sigut creada correctament" + updated: "La pàgina s'ha editat correctament" + deleted: "La pàgina s'ha esborrat sense problemes" + pageSetting: "Configuració de la pàgina" + nameAlreadyExists: "L'adreça URL de la pàgina ja existeix" + invalidNameTitle: "L'adreça URL de la pàgina no és vàlida" + invalidNameText: "Assegurat que el títol de la pàgina no és buit" + editThisPage: "Editar la pàgina" viewSource: "Veure l'origen " viewPage: "Veure les teves pàgines " like: "M'agrada " @@ -2150,6 +2354,7 @@ _pages: eyeCatchingImageSet: "Escull una miniatura" eyeCatchingImageRemove: "Esborrar la miniatura" chooseBlock: "Afegeix un bloc" + enterSectionTitle: "Escriu el títol de la secció" selectType: "Seleccionar tipus" contentBlocks: "Contingut" inputBlocks: "Entrada " @@ -2160,6 +2365,8 @@ _pages: section: "Secció " image: "Imatges" button: "Botó " + dynamic: "Blocs dinàmics" + dynamicDescription: "Aquest bloc és antic. Ara en endavant fes servir {play}" note: "Incorporar una Nota" _note: id: "ID de la publicació" @@ -2189,29 +2396,54 @@ _notification: sendTestNotification: "Enviar notificació de prova" notificationWillBeDisplayedLikeThis: "Les notificacions és veure'n així " reactedBySomeUsers: "Han reaccionat {n} usuaris" + likedBySomeUsers: "A {n} usuaris els hi agrada la teva nota" renotedBySomeUsers: "L'han impulsat {n} usuaris" + followedBySomeUsers: "Et segueixen {n} usuaris" + flushNotification: "Netejar notificacions" + exportOfXCompleted: "Completada l'exportació de {n}" _types: all: "Tots" + note: "Notes noves" follow: "Seguint" mention: "Menció" + reply: "Respostes" renote: "Renotar" quote: "Citar" reaction: "Reaccions" + pollEnded: "Enquesta terminada" + receiveFollowRequest: "Rebuda una petició de seguiment" + followRequestAccepted: "Petició de seguiment acceptada" + roleAssigned: "Rol donat" + achievementEarned: "Assoliment desbloquejat" + exportCompleted: "Exportació completada" + login: "Iniciar sessió" + test: "Prova la notificació" + app: "Notificacions d'aplicacions" _actions: followBack: "t'ha seguit també" reply: "Respondre" renote: "Renotar" _deck: + alwaysShowMainColumn: "Mostrar sempre la columna principal" columnAlign: "Alinea les columnes" addColumn: "Afig una columna" + newNoteNotificationSettings: "Configuració de notificacions per a notes noves" + configureColumn: "Configuració de columnes" swapLeft: "Mou a l’esquerra" swapRight: "Mou a la dreta" swapUp: "Mou cap amunt" swapDown: "Mou cap avall" + stackLeft: "Pila a la columna esquerra" popRight: "Col·loca a la dreta" profile: "Perfil" newProfile: "Perfil nou" deleteProfile: "Elimina el perfil" + introduction: "Crea la interfície perfecta posant les columnes allà on vulguis!" + introduction2: "Fes clic al botó + de la dreta per afegir noves columnes sempre que vulguis." + widgetsIntroduction: "Selecciona \"Editar ginys\" a la columna del menú i afegeix un." + useSimpleUiForNonRootPages: "Usa una interfície senzilla per a les pàgines navegades" + usedAsMinWidthWhenFlexible: "L'amplada mínima es farà servir quan \"Ajust automàtic de l'amplada\" estigui activat" + flexible: "Ajust automàtic de l'amplada" _columns: main: "Principal" widgets: "Ginys" @@ -2222,17 +2454,82 @@ _deck: channel: "Canals" mentions: "Mencions" direct: "Publicacions directes" + roleTimeline: "Línia de temps dels rols" +_dialog: + charactersExceeded: "Has arribat al màxim de caràcters! Actualment és {current} de {max}" + charactersBelow: "Ets per sota del mínim de caràcters! Actualment és {current} de {min}" +_disabledTimeline: + title: "Línia de tems desactivada" + description: "No pots fer servir aquesta línia de temps amb els teus rols actuals." +_drivecleaner: + orderBySizeDesc: "Mida del fitxer descendent" + orderByCreatedAtAsc: "Data ascendent" _webhookSettings: + createWebhook: "Crear un Webhook" + modifyWebhook: "Modificar un Webhook" name: "Nom" + secret: "Secret" + trigger: "Activador" active: "Activat" + _events: + follow: "Quan se segueix a un usuari" + followed: "Quan et segueixen" + note: "Quan es publica una nota" + reply: "Quan es rep una resposta" + renote: "Quan es renoti" + reaction: "Quan es rep una reacció " + mention: "Quan et mencionen" + _systemEvents: + abuseReport: "Quan reps un nou informe de moderació " + abuseReportResolved: "Quan resols un informe de moderació " + userCreated: "Quan es crea un usuari" + deleteConfirm: "Segur que vols esborrar el webhook?" + testRemarks: "Si feu clic al botó a la dreta de l'interruptor, podeu enviar un webhook de prova amb dades dummy." +_abuseReport: + _notificationRecipient: + createRecipient: "Afegeix un destinatari a l'informe de moderació " + modifyRecipient: "Editar un destinatari en l'informe de moderació " + recipientType: "Tipus de notificació " + _recipientType: + mail: "Correu electrònic" + webhook: "Webhook" + _captions: + mail: "Enviar un correu electrònic a tots els moderadors quan es rep un informe de moderació " + webhook: "Enviar una notificació al SystemWebhook quan es rebi o es resolgui un informe de moderació " + keywords: "Paraules clau" + notifiedUser: "Usuaris que s'han de notificar " + notifiedWebhook: "Webhook que s'ha de fer servir" + deleteConfirm: "Segur que vols esborrar el destinatari de l'informe de moderació?" _moderationLogTypes: + createRole: "Rol creat" + deleteRole: "Rol esborrat" + updateRole: "Rol actualitzat" + assignRole: "Assignat al rol" + unassignRole: "Esborrat del rol" suspend: "Suspèn" + unsuspend: "Suspensió treta" + addCustomEmoji: "Afegit emoji personalitzat" + updateCustomEmoji: "Actualitzat emoji personalitzat" + deleteCustomEmoji: "Esborrat emoji personalitzat" + updateServerSettings: "Configuració del servidor actualitzada" + updateUserNote: "Nota de moderació actualitzada" + deleteDriveFile: "Fitxer esborrat" + deleteNote: "Nota esborrada" + createGlobalAnnouncement: "Anunci global creat" + createUserAnnouncement: "Anunci individual creat" + updateGlobalAnnouncement: "Anunci global actualitzat" + updateUserAnnouncement: "Anunci individual actualitzat " + deleteGlobalAnnouncement: "Anunci global esborrat" + deleteUserAnnouncement: "Anunci individual esborrat " resetPassword: "Restableix la contrasenya" suspendRemoteInstance: "Servidor remot suspès " unsuspendRemoteInstance: "S'ha tret la suspensió del servidor remot" + updateRemoteInstanceNote: "Nota de moderació de la instància remota actualitzada" markSensitiveDriveFile: "Fitxer marcat com a sensible" unmarkSensitiveDriveFile: "S'ha tret la marca de sensible del fitxer" resolveAbuseReport: "Informe resolt" + forwardAbuseReport: "Informe reenviat" + updateAbuseReportNote: "Nota de moderació d'un informe actualitzat" createInvitation: "Crear codi d'invitació " createAd: "Anunci creat" deleteAd: "Anunci esborrat" @@ -2242,6 +2539,16 @@ _moderationLogTypes: deleteAvatarDecoration: "S'ha esborrat la decoració de l'avatar " unsetUserAvatar: "Esborrar l'avatar d'aquest usuari" unsetUserBanner: "Esborrar el bàner d'aquest usuari" + createSystemWebhook: "Crear un SystemWebhook" + updateSystemWebhook: "Actualitzar SystemWebhook" + deleteSystemWebhook: "Esborrar SystemWebhook" + createAbuseReportNotificationRecipient: "Crear un destinatari per l'informe de moderació " + updateAbuseReportNotificationRecipient: "Actualitzar destinatari per l'informe de moderació " + deleteAbuseReportNotificationRecipient: "Esborrar destinatari de l'informe de moderació " + deleteAccount: "Esborrar el compte " + deletePage: "Esborrar la pàgina" + deleteFlash: "Esborrar el guió" + deleteGalleryPost: "Esborrar la publicació de la galeria" _fileViewer: title: "Detall del fitxer" type: "Tipus de fitxer" @@ -2268,5 +2575,54 @@ _externalResourceInstaller: _errors: _invalidParams: title: "Paràmetres no vàlids " + description: "No hi ha suficient informació per carregar les dades del lloc extern. Confirma l'URL que hi ha escrita." + _resourceTypeNotSupported: + title: "El recurs extern no està suportat." + description: "Aquesta mena de recurs no està suportat. Contacta amb l'administrador." + _failedToFetch: + title: "Ha fallat l'obtenció de dades" + fetchErrorDescription: "Ha aparegut un error comunicant-se amb el lloc extern. Si després d'intentar-ho un altre cop no es resol, contacta amb l'administrador." + parseErrorDescription: "Ha aparegut un error processant les dades carregades del lloc extern. Contacta amb l'administrador." + _hashUnmatched: + title: "Ha fallat la verificació de les dades" + description: "Ha aparegut un error verificant les dades obtingudes. Com a mesura de seguretat la instal·lació no pot continuar. Contacta amb l'administrador." + _pluginParseFailed: + title: "Error d'AiScript" + description: "Les dades sol·licitades s'han obtingut correctament, però hem trobat un error durant el processament d'AiScript. Contacta amb l'autor de l'afegit. Detalls de l'error es pot veure a la consola JavaScript." + _pluginInstallFailed: + title: "La instal·lació de l'afegit a fallat" + description: "Ha aparegut un error durant la instal·lació de l'afegit. Intenta-ho una altra vegada. El detall de l'error es pot veure a la consola JavaScript." + _themeParseFailed: + title: "Ha fallat el processament del tema" + description: "Les dades sol·licitades s'han obtingut correctament, però hem trobat un error durant el processament del tema. Contacta amb l'autor de l'afegit. Detalls de l'error es pot veure a la consola JavaScript." + _themeInstallFailed: + title: "La instal·lació del tema a fallat" + description: "Ha aparegut un error durant la instal·lació del tema. Intenta-ho una altra vegada. El detall de l'error es pot veure a la consola JavaScript." +_dataSaver: + _media: + title: "Carregant multimèdia " + description: "Desactiva la càrrega automàtica d'imatges i vídeos. Les imatges i els vídeos amagats es carregaran quan es faci clic a sobre." + _avatar: + title: "Avatars animats" + description: "Detenir l'animació dels avatars animats. Les imatges animades solen tenir un pes més gran que les imatges normals, reduint el tràfic disponible." + _urlPreview: + title: "Miniatures vista prèvia de l'URL" + description: "Les imatges en miniatura que serveixen com a vista prèvia de les URLs no es tornaran a carregar." + _code: + title: "Ressaltat del codi " _reversi: total: "Total" +_embedCodeGen: + title: "Personalitza el codi per incrustar" + header: "Mostrar la capçalera" + autoload: "Carregar automàticament (no recomanat)" + maxHeight: "Alçada màxima" + maxHeightDescription: "0 anul·la la configuració màxima. Per evitar que continuï creixent verticalment, especifiqui qualsevol valor." + maxHeightWarn: "El límit màxim d'alçada és nul (0). Si això no és un canvi previst, estableix el màxim d'alçada a un cert valor." + previewIsNotActual: "La visualització és diferent de la que es mostra quan s'implanta." + rounded: "Angle recte" + border: "Afegeix un marc al contenidor" + applyToPreview: "Aplica a la vista prèvia" + generateCode: "Crea el codi per incrustar" + codeGenerated: "Codi generat" + codeGeneratedDescription: "Si us plau, enganxeu el codi generat al lloc web." diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index c8a0b0cb28..caf6d6e163 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -471,7 +471,6 @@ uiLanguage: "Jazyk uživatelského rozhraní" aboutX: "O {x}" emojiStyle: "Styl emoji" native: "Výchozí" -disableDrawer: "Nepoužívat šuplíkové menu" showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši" noHistory: "Žádná historie" signinHistory: "Historie přihlášení" @@ -658,10 +657,7 @@ abuseReported: "Nahlášení bylo odesláno. Děkujeme převelice." reporter: "Nahlásil" reporteeOrigin: "Původ nahlášení" reporterOrigin: "Původ nahlasovače" -forwardReport: "Přeposlat nahlášení do vzdálené instance" -forwardReportIsAnonymous: "Místo vašeho účtu se ve vzdálené instanci zobrazí anonymní systémový účet jako nahlašovač." send: "Odeslat" -abuseMarkAsResolved: "Označit nahlášení jako vyřešené" openInNewTab: "Otevřít v nové kartě" openInSideView: "Otevřít v bočním panelu" defaultNavigationBehaviour: "Výchozí chování navigace" @@ -1633,7 +1629,6 @@ _theme: buttonBg: "Pozadí tlačítka" buttonHoverBg: "Pozadí tlačítka (Hover)" inputBorder: "Ohraničení vstupního pole" - listItemHoverBg: "Pozadí položky seznamu (Hover)" driveFolderBg: "Pozadí složky disku" wallpaperOverlay: "Překrytí tapety" badge: "Odznak" @@ -1645,8 +1640,6 @@ _sfx: note: "Poznámky" noteMy: "Moje poznámka" notification: "Oznámení" - antenna: "Antény" - channel: "Oznámení kanálu" _ago: future: "Budoucí" justNow: "Teď" @@ -1965,6 +1958,7 @@ _notification: receiveFollowRequest: "Obdržené žádosti o sledování" followRequestAccepted: "Přijaté žádosti o sledování" achievementEarned: "Úspěch odemčen" + login: "Přihlásit se" app: "Oznámení z propojených aplikací" _actions: followBack: "vás začal sledovat zpět" @@ -2012,7 +2006,6 @@ _webhookSettings: createWebhook: "Vytvořit Webhook" name: "Jméno" secret: "Tajné" - events: "Události Webhook" active: "Zapnuto" _events: follow: "Při sledování uživatele" @@ -2022,6 +2015,10 @@ _webhookSettings: renote: "Při renotaci poznámky" reaction: "Při obdržení reakce" mention: "Při zmínce" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: suspend: "Zmrazit" resetPassword: "Resetovat heslo" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 9e42e01252..4e2bd06934 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -491,7 +491,6 @@ uiLanguage: "Sprache der Benutzeroberfläche" aboutX: "Über {x}" emojiStyle: "Emoji-Stil" native: "Nativ" -disableDrawer: "Keine ausfahrbaren Menüs verwenden" showNoteActionsOnlyHover: "Notizmenü nur bei Mouseover anzeigen" noHistory: "Kein Verlauf gefunden" signinHistory: "Anmeldungsverlauf" @@ -687,10 +686,7 @@ abuseReported: "Deine Meldung wurde versendet. Vielen Dank." reporter: "Melder" reporteeOrigin: "Herkunft des Gemeldeten" reporterOrigin: "Herkunft des Meldenden" -forwardReport: "Meldung an fremde Instanz weiterleiten" -forwardReportIsAnonymous: "Anstatt deines Benutzerkontos wird bei der fremden Instanz ein anonymes Systemkonto als Melder angezeigt." send: "Senden" -abuseMarkAsResolved: "Meldung als gelöst markieren" openInNewTab: "In neuem Tab öffnen" openInSideView: "In Seitenansicht öffnen" defaultNavigationBehaviour: "Standardnavigationsverhalten" @@ -1788,7 +1784,6 @@ _theme: buttonBg: "Hintergrund von Schaltflächen" buttonHoverBg: "Hintergrund von Schaltflächen (Mouseover)" inputBorder: "Rahmen von Eingabefeldern" - listItemHoverBg: "Hintergrund von Listeneinträgen (Mouseover)" driveFolderBg: "Hintergrund von Drive-Ordnern" wallpaperOverlay: "Hintergrundbild-Overlay" badge: "Wappen" @@ -1800,8 +1795,6 @@ _sfx: note: "Notizen" noteMy: "Meine Notizen" notification: "Benachrichtigungen" - antenna: "Antennen" - channel: "Kanalbenachrichtigung" _ago: future: "Zukunft" justNow: "Gerade eben" @@ -2144,6 +2137,7 @@ _notification: receiveFollowRequest: "Erhaltene Follow-Anfragen" followRequestAccepted: "Akzeptierte Follow-Anfragen" achievementEarned: "Errungenschaft freigeschaltet" + login: "Anmelden" app: "Benachrichtigungen von Apps" _actions: followBack: "folgt dir nun auch" @@ -2193,7 +2187,6 @@ _webhookSettings: createWebhook: "Webhook erstellen" name: "Name" secret: "Secret" - events: "Webhook-Ereignisse" active: "Aktiviert" _events: follow: "Wenn du jemandem folgst" @@ -2203,6 +2196,10 @@ _webhookSettings: renote: "Wenn du ein Renote erhältst" reaction: "Wenn du eine Reaktion erhältst" mention: "Wenn du erwähnt wirst" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: createRole: "Rolle erstellt" deleteRole: "Rolle gelöscht" diff --git a/locales/el-GR.yml b/locales/el-GR.yml index 2098c7ef50..4657842ca5 100644 --- a/locales/el-GR.yml +++ b/locales/el-GR.yml @@ -301,8 +301,6 @@ _theme: _sfx: note: "Σημειώματα" notification: "Ειδοποιήσεις" - antenna: "Αντένες" - channel: "Ειδοποιήσεις καναλιών" _ago: future: "Μελλοντικό" justNow: "Μόλις τώρα" @@ -380,6 +378,7 @@ _notification: renote: "Κοινοποίηση σημειώματος" quote: "Παράθεση" reaction: "Αντιδράσεις" + login: "Σύνδεση" _actions: reply: "Απάντηση" renote: "Κοινοποίηση σημειώματος" diff --git a/locales/en-US.yml b/locales/en-US.yml index c20a1ac7d8..6ea7fb4f8d 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -8,6 +8,9 @@ search: "Search" notifications: "Notifications" username: "Username" password: "Password" +initialPasswordForSetup: "Initial password for setup" +initialPasswordIsIncorrect: "Initial password for setup is incorrect" +initialPasswordForSetupDescription: "Use the password you entered in the configuration file if you installed Misskey yourself.\n If you are using a Misskey hosting service, use the password provided.\n If you have not set a password, leave it blank to continue." forgotPassword: "Forgot password" fetchingAsApObject: "Fetching from the Fediverse..." ok: "OK" @@ -60,6 +63,7 @@ copyFileId: "Copy file ID" copyFolderId: "Copy folder ID" copyProfileUrl: "Copy profile URL" searchUser: "Search for a user" +searchThisUsersNotes: "Search this user’s notes" reply: "Reply" loadMore: "Load more" showMore: "Show more" @@ -108,7 +112,7 @@ enterEmoji: "Enter an emoji" renote: "Renote" unrenote: "Remove renote" renoted: "Renoted." -renotedToX: "Renote from {name} users。" +renotedToX: "Renoted to {name}." cantRenote: "This post can't be renoted." cantReRenote: "A renote can't be renoted." quote: "Quote" @@ -125,8 +129,8 @@ add: "Add" reaction: "Reactions" reactions: "Reactions" emojiPicker: "Emoji picker" -pinnedEmojisForReactionSettingDescription: "Set the emojis which should be pinned and displayed immediately when reacting." -pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker" +pinnedEmojisForReactionSettingDescription: "Set the emojis to be pinned and displayed when reacting." +pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker." emojiPickerDisplay: "Emoji picker display" overwriteFromPinnedEmojisForReaction: "Override from reaction settings" overwriteFromPinnedEmojis: "Override from general settings" @@ -154,6 +158,7 @@ editList: "Edit list" selectChannel: "Select a channel" selectAntenna: "Select an antenna" editAntenna: "Edit antenna" +createAntenna: "Create an antenna" selectWidget: "Select a widget" editWidgets: "Edit widgets" editWidgetsExit: "Done" @@ -165,7 +170,7 @@ emojiUrl: "Emoji URL" addEmoji: "Add an emoji" settingGuide: "Recommended settings" cacheRemoteFiles: "Cache remote files" -cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote instance. Disabling this will decrease storage usage, but increase traffic, as thumbnails will not be generated." +cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote servers. Disabling this will decrease storage usage, but increase traffic, as thumbnails will not be generated." youCanCleanRemoteFilesCache: "You can clear the cache by clicking the 🗑️ button in the file management view." cacheRemoteSensitiveFiles: "Cache sensitive remote files" cacheRemoteSensitiveFilesDescription: "When this setting is disabled, sensitive remote files are loaded directly from the remote instance without caching." @@ -180,6 +185,10 @@ addAccount: "Add account" reloadAccountsList: "Reload account list" loginFailed: "Failed to sign in" showOnRemote: "View on remote instance" +continueOnRemote: "Continue on a remote server" +chooseServerOnMisskeyHub: "Choose a server from the Misskey Hub" +specifyServerHost: "Specify a server host directly" +inputHostName: "Enter the domain" general: "General" wallpaper: "Wallpaper" setWallpaper: "Set wallpaper" @@ -190,6 +199,7 @@ followConfirm: "Are you sure that you want to follow {name}?" proxyAccount: "Proxy account" proxyAccountDescription: "A proxy account is an account that acts as a remote follower for users under certain conditions. For example, when a user adds a remote user to the list, the remote user's activity will not be delivered to the instance if no local user is following that user, so the proxy account will follow instead." host: "Host" +selectSelf: "Select myself" selectUser: "Select a user" recipient: "Recipient" annotation: "Comments" @@ -205,6 +215,7 @@ perDay: "Per Day" stopActivityDelivery: "Stop sending activities" blockThisInstance: "Block this instance" silenceThisInstance: "Silence this instance" +mediaSilenceThisInstance: "Media-silence this server" operations: "Operations" software: "Software" version: "Version" @@ -225,7 +236,11 @@ clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote blockedInstances: "Blocked Instances" blockedInstancesDescription: "List the hostnames of the instances you want to block separated by linebreaks. Listed instances will no longer be able to communicate with this instance." silencedInstances: "Silenced instances" -silencedInstancesDescription: "List the hostnames of the instances that you want to silence. All accounts of the listed instances will be treated as silenced, can only make follow requests, and cannot mention local accounts if not followed. This will not affect blocked instances." +silencedInstancesDescription: "List the host names of the servers that you want to silence, separated by a new line. All accounts belonging to the listed servers will be treated as silenced, and can only make follow requests, and cannot mention local accounts if not followed. This will not affect the blocked servers." +mediaSilencedInstances: "Media-silenced servers" +mediaSilencedInstancesDescription: "List the host names of the servers that you want to media-silence, separated by a new line. All accounts belonging to the listed servers will be treated as sensitive, and can't use custom emojis. This will not affect the blocked servers." +federationAllowedHosts: "Federation allowed servers" +federationAllowedHostsDescription: "Specify the hostnames of the servers you want to allow federation separated by line breaks." muteAndBlock: "Mutes and Blocks" mutedUsers: "Muted users" blockedUsers: "Blocked users" @@ -316,6 +331,7 @@ selectFile: "Select a file" selectFiles: "Select files" selectFolder: "Select a folder" selectFolders: "Select folders" +fileNotSelected: "" renameFile: "Rename file" folderName: "Folder name" createFolder: "Create a folder" @@ -323,6 +339,7 @@ renameFolder: "Rename this folder" deleteFolder: "Delete this folder" folder: "Folder" addFile: "Add a file" +showFile: "Show files" emptyDrive: "Your Drive is empty" emptyFolder: "This folder is empty" unableToDelete: "Unable to delete" @@ -387,7 +404,7 @@ mcaptcha: "mCaptcha" enableMcaptcha: "Enable mCaptcha" mcaptchaSiteKey: "Site key" mcaptchaSecretKey: "Secret key" -mcaptchaInstanceUrl: "mCaptcha instance URL" +mcaptchaInstanceUrl: "mCaptcha server URL" recaptcha: "reCAPTCHA" enableRecaptcha: "Enable reCAPTCHA" recaptchaSiteKey: "Site key" @@ -437,6 +454,7 @@ totpDescription: "Use an authenticator app to enter one-time passwords" moderator: "Moderator" moderation: "Moderation" moderationNote: "Moderation note" +moderationNoteDescription: "You can fill in notes that will be shared only among moderators." addModerationNote: "Add moderation note" moderationLogs: "Moderation logs" nUsersMentioned: "Mentioned by {n} users" @@ -476,6 +494,7 @@ noMessagesYet: "No messages yet" newMessageExists: "There are new messages" onlyOneFileCanBeAttached: "You can only attach one file to a message" signinRequired: "Please register or sign in before continuing" +signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server." invitations: "Invites" invitationCode: "Invitation code" checking: "Checking..." @@ -497,7 +516,10 @@ uiLanguage: "User interface language" aboutX: "About {x}" emojiStyle: "Emoji style" native: "Native" -disableDrawer: "Don't use drawer-style menus" +menuStyle: "Menu style" +style: "Style" +drawer: "Drawer" +popup: "Pop up" showNoteActionsOnlyHover: "Only show note actions on hover" showReactionsCount: "See the number of reactions in notes" noHistory: "No history available" @@ -580,6 +602,8 @@ ascendingOrder: "Ascending" descendingOrder: "Descending" scratchpad: "Scratchpad" scratchpadDescription: "The Scratchpad provides an environment for AiScript experiments. You can write, execute, and check the results of it interacting with Misskey in it." +uiInspector: "UI inspector" +uiInspectorDescription: "You can see the UI component server list on memory. UI component will be generated by Ui:C: function." output: "Output" script: "Script" disablePagesScript: "Disable AiScript on Pages" @@ -696,10 +720,7 @@ abuseReported: "Your report has been sent. Thank you very much." reporter: "Reporter" reporteeOrigin: "Reportee Origin" reporterOrigin: "Reporter Origin" -forwardReport: "Forward report to remote instance" -forwardReportIsAnonymous: "Instead of your account, an anonymous system account will be displayed as reporter at the remote instance." send: "Send" -abuseMarkAsResolved: "Mark report as resolved" openInNewTab: "Open in new tab" openInSideView: "Open in side view" defaultNavigationBehaviour: "Default navigation behavior" @@ -836,6 +857,7 @@ administration: "Management" accounts: "Accounts" switch: "Switch" noMaintainerInformationWarning: "Maintainer information is not configured." +noInquiryUrlWarning: "Inquiry URL isn’t set" noBotProtectionWarning: "Bot protection is not configured." configure: "Configure" postToGallery: "Create new gallery post" @@ -900,6 +922,7 @@ followersVisibility: "Visibility of followers" continueThread: "View thread continuation" deleteAccountConfirm: "This will irreversibly delete your account. Proceed?" incorrectPassword: "Incorrect password." +incorrectTotp: "The one-time password is incorrect or has expired." voteConfirm: "Confirm your vote for \"{choice}\"?" hide: "Hide" useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile" @@ -1025,6 +1048,7 @@ thisPostMayBeAnnoyingHome: "Post to home timeline" thisPostMayBeAnnoyingCancel: "Cancel" thisPostMayBeAnnoyingIgnore: "Post anyway" collapseRenotes: "Collapse renotes you've already seen" +collapseRenotesDescription: "Collapse notes that you've reacted to or renoted before." internalServerError: "Internal Server Error" internalServerErrorDescription: "The server has run into an unexpected error." copyErrorInfo: "Copy error details" @@ -1065,7 +1089,7 @@ enableChartsForRemoteUser: "Generate remote user data charts" enableChartsForFederatedInstances: "Generate remote instance data charts" showClipButtonInNoteFooter: "Add \"Clip\" to note action menu" reactionsDisplaySize: "Reaction display size" -limitWidthOfReaction: "Limits the maximum width of reactions and display them in reduced size." +limitWidthOfReaction: "Limit the maximum width of reactions and display them in reduced size." noteIdOrUrl: "Note ID or URL" video: "Video" videos: "Videos" @@ -1098,6 +1122,8 @@ preservedUsernames: "Reserved usernames" preservedUsernamesDescription: "List usernames to reserve separated by linebreaks. These will become unable during normal account creation, but can be used by administrators to manually create accounts. Already existing accounts using these usernames will not be affected." createNoteFromTheFile: "Compose note from this file" archive: "Archive" +archived: "Archived" +unarchive: "Unarchive" channelArchiveConfirmTitle: "Really archive {name}?" channelArchiveConfirmDescription: "An archived channel won't appear in the channel list or search results anymore. New posts can also not be added to it anymore." thisChannelArchived: "This channel has been archived." @@ -1108,6 +1134,9 @@ preventAiLearning: "Reject usage in Machine Learning (Generative AI)" preventAiLearningDescription: "Requests crawlers to not use posted text or image material etc. in machine learning (Predictive / Generative AI) data sets. This is achieved by adding a \"noai\" HTML-Response flag to the respective content. A complete prevention can however not be achieved through this flag, as it may simply be ignored." options: "Options" specifyUser: "Specific user" +lookupConfirm: "Do you want to look up?" +openTagPageConfirm: "Do you want to open a hashtag page?" +specifyHost: "Specific host" failedToPreviewUrl: "Could not preview" update: "Update" rolesThatCanBeUsedThisEmojiAsReaction: "Roles that can use this emoji as reaction" @@ -1236,9 +1265,35 @@ launchApp: "Launch the app" useNativeUIForVideoAudioPlayer: "Use UI of browser when play video and audio" keepOriginalFilename: "Keep original file name" keepOriginalFilenameDescription: "If you turn off this setting, files names will be replaced with random string automatically when you upload files." -noDescription: "There is not the explanation" +noDescription: "There is no explanation" alwaysConfirmFollow: "Always confirm when following" inquiry: "Contact" +tryAgain: "Please try again later" +confirmWhenRevealingSensitiveMedia: "Confirm when revealing sensitive media" +sensitiveMediaRevealConfirm: "This might be a sensitive media. Are you sure to reveal?" +createdLists: "Created lists" +createdAntennas: "Created antennas" +fromX: "From {x}" +genEmbedCode: "Generate embed code" +noteOfThisUser: "Notes by this user" +clipNoteLimitExceeded: "No more notes can be added to this clip." +performance: "Performance" +modified: "Modified" +discard: "Discard" +thereAreNChanges: "There are {n} change(s)" +signinWithPasskey: "Sign in with Passkey" +unknownWebAuthnKey: "Unknown Passkey" +passkeyVerificationFailed: "Passkey verification has failed." +passkeyVerificationSucceededButPasswordlessLoginDisabled: "Passkey verification has succeeded but password-less login is disabled." +messageToFollower: "Message to followers" +target: "Target" +_abuseUserReport: + forward: "Forward" + forwardDescription: "Forward the report to a remote server as an anonymous system account." + resolve: "Resolve" + accept: "Accept" + reject: "Reject" + resolveTutorial: "If the report is legitimate in content, select \"Accept\" to mark the case as resolved in the affirmative.\nIf the content of the report is not legitimate, select \"Reject\" to mark the case as resolved in the negative." _delivery: status: "Delivery status" stop: "Suspended" @@ -1341,7 +1396,7 @@ _initialTutorial: _exampleNote: cw: "This will surely make you hungry!" note: "Just had a chocolate-glazed donut 🍩😋" - useCases: "This is used when following the server guidelines for necessary notes or for self-restriction of spoiler or sensitive text." + useCases: "This is used when following the server guidelines, for necessary notes, or for self-restriction of spoiler or sensitive text." _howToMakeAttachmentsSensitive: title: "How to Mark Attachments as Sensitive?" description: "For attachments that are required by server guidelines or that should not be left intact, add a \"sensitive\" flag." @@ -1373,6 +1428,9 @@ _serverSettings: fanoutTimelineDescription: "Greatly increases performance of timeline retrieval and reduces load on the database when enabled. In exchange, memory usage of Redis will increase. Consider disabling this in case of low server memory or server instability." fanoutTimelineDbFallback: "Fallback to database" fanoutTimelineDbFallbackDescription: "When enabled, the timeline will fall back to the database for additional queries if the timeline is not cached. Disabling it further reduces the server load by eliminating the fallback process, but limits the range of timelines that can be retrieved." + reactionsBufferingDescription: "When enabled, performance during reaction creation will be greatly improved, reducing the load on the database. However, Redis memory usage will increase." + inquiryUrl: "Inquiry URL" + inquiryUrlDescription: "Specify a URL for the inquiry form to the server maintainer or a web page for the contact information." _accountMigration: moveFrom: "Migrate another account to this one" moveFromSub: "Create alias to another account" @@ -1689,6 +1747,7 @@ _role: canManageAvatarDecorations: "Manage avatar decorations" driveCapacity: "Drive capacity" alwaysMarkNsfw: "Always mark files as NSFW" + canUpdateBioMedia: "Can edit an icon or a banner image" pinMax: "Maximum number of pinned notes" antennaMax: "Maximum number of antennas" wordMuteMax: "Maximum number of characters allowed in word mutes" @@ -1703,6 +1762,11 @@ _role: canSearchNotes: "Usage of note search" canUseTranslator: "Translator usage" avatarDecorationLimit: "Maximum number of avatar decorations that can be applied" + canImportAntennas: "Allow importing antennas" + canImportBlocking: "Allow importing blocking" + canImportFollowing: "Allow importing following" + canImportMuting: "Allow importing muting" + canImportUserLists: "Allow importing lists" _condition: roleAssignedTo: "Assigned to manual roles" isLocal: "Local user" @@ -1920,7 +1984,6 @@ _theme: buttonBg: "Button background" buttonHoverBg: "Button background (Hover)" inputBorder: "Input field border" - listItemHoverBg: "List item background (Hover)" driveFolderBg: "Drive folder background" wallpaperOverlay: "Wallpaper overlay" badge: "Badge" @@ -1932,8 +1995,6 @@ _sfx: note: "New note" noteMy: "Own note" notification: "Notifications" - antenna: "Antennas" - channel: "Channel notifications" reaction: "On choosing a reaction" _soundSettings: driveFile: "Use an audio file in Drive." @@ -1942,6 +2003,7 @@ _soundSettings: driveFileTypeWarnDescription: "Select an audio file" driveFileDurationWarn: "The audio is too long." driveFileDurationWarnDescription: "Long audio may disrupt using Misskey. Still continue?" + driveFileError: "It couldn't load the sound. Please change the setting." _ago: future: "Future" justNow: "Just now" @@ -2059,7 +2121,7 @@ _permissions: "read:admin:invite-codes": "View invite codes" "write:admin:announcements": "Manage announcements" "read:admin:announcements": "View announcements" - "write:admin:avatar-decorations": "Manage avatar decorations" + "write:admin:avatar-decorations": "Can manage avatar decorations" "read:admin:avatar-decorations": "View avatar decorations" "write:admin:federation": "Manage federation data" "write:admin:account": "Manage user account" @@ -2198,6 +2260,9 @@ _profile: changeBanner: "Change banner" verifiedLinkDescription: "By entering an URL that contains a link to your profile here, an ownership verification icon can be displayed next to the field." avatarDecorationMax: "You can add up to {max} decorations." + followedMessage: "Message when you are followed" + followedMessageDescription: "You can set a short message to be displayed to the recipient when they follow you." + followedMessageDescriptionForLockedAccount: "If you have set up that follow requests require approval, this will be displayed when you grant a follow request." _exportOrImport: allNotes: "All notes" favoritedNotes: "Favorite notes" @@ -2290,6 +2355,7 @@ _pages: eyeCatchingImageSet: "Set thumbnail" eyeCatchingImageRemove: "Delete thumbnail" chooseBlock: "Add a block" + enterSectionTitle: "Enter a section title" selectType: "Select a type" contentBlocks: "Content" inputBlocks: "Input" @@ -2335,6 +2401,8 @@ _notification: renotedBySomeUsers: "Renote from {n} users" followedBySomeUsers: "Followed by {n} users" flushNotification: "Clear notifications" + exportOfXCompleted: "Export of {x} has been completed" + login: "Someone logged in" _types: all: "All" note: "New notes" @@ -2349,6 +2417,9 @@ _notification: followRequestAccepted: "Accepted follow requests" roleAssigned: "Role given" achievementEarned: "Achievement unlocked" + exportCompleted: "The export has been completed" + login: "Sign In" + test: "Notification test" app: "Notifications from linked apps" _actions: followBack: "followed you back" @@ -2358,6 +2429,7 @@ _deck: alwaysShowMainColumn: "Always show main column" columnAlign: "Align columns" addColumn: "Add column" + newNoteNotificationSettings: "Notification setting for new notes" configureColumn: "Column settings" swapLeft: "Swap with the left column" swapRight: "Swap with the right column" @@ -2396,9 +2468,10 @@ _drivecleaner: orderByCreatedAtAsc: "Ascending Dates" _webhookSettings: createWebhook: "Create Webhook" + modifyWebhook: "Modify Webhook" name: "Name" secret: "Secret" - events: "Webhook Events" + trigger: "Trigger" active: "Enabled" _events: follow: "When following a user" @@ -2408,6 +2481,27 @@ _webhookSettings: renote: "When renoted" reaction: "When receiving a reaction" mention: "When being mentioned" + _systemEvents: + abuseReport: "When received a new report" + abuseReportResolved: "When resolved report" + userCreated: "When user is created" + deleteConfirm: "Are you sure you want to delete the Webhook?" + testRemarks: "Click the button to the right of the switch to send a test Webhook with dummy data." +_abuseReport: + _notificationRecipient: + createRecipient: "Add a recipient for reports" + modifyRecipient: "Edit a recipient for reports" + recipientType: "Notification type" + _recipientType: + mail: "Email" + webhook: "Webhook" + _captions: + mail: "Send the email to moderators' email addresses when you receive reports." + webhook: "Send a notification to System Webhook when you receive or resolve reports." + keywords: "Keywords" + notifiedUser: "Users to notify" + notifiedWebhook: "Webhook to use" + deleteConfirm: "Are you sure that you want to delete the notification recipient?" _moderationLogTypes: createRole: "Role created" deleteRole: "Role deleted" @@ -2436,6 +2530,8 @@ _moderationLogTypes: markSensitiveDriveFile: "File marked as sensitive" unmarkSensitiveDriveFile: "File unmarked as sensitive" resolveAbuseReport: "Report resolved" + forwardAbuseReport: "Report forwarded" + updateAbuseReportNote: "Moderation note of a report updated" createInvitation: "Invite generated" createAd: "Ad created" deleteAd: "Ad deleted" @@ -2443,8 +2539,18 @@ _moderationLogTypes: createAvatarDecoration: "Avatar decoration created" updateAvatarDecoration: "Avatar decoration updated" deleteAvatarDecoration: "Avatar decoration deleted" - unsetUserAvatar: "Unset this user's avatar" - unsetUserBanner: "Unset this user's banner" + unsetUserAvatar: "User avatar unset" + unsetUserBanner: "User banner unset" + createSystemWebhook: "System Webhook created" + updateSystemWebhook: "System Webhook updated" + deleteSystemWebhook: "System Webhook deleted" + createAbuseReportNotificationRecipient: "Recipient for reports created" + updateAbuseReportNotificationRecipient: "Recipient for reports updated" + deleteAbuseReportNotificationRecipient: "Recipient for reports deleted" + deleteAccount: "Account deleted" + deletePage: "Page deleted" + deleteFlash: "Play deleted" + deleteGalleryPost: "Gallery post deleted" _fileViewer: title: "File details" type: "File type" @@ -2576,3 +2682,22 @@ _mediaControls: pip: "Picture in Picture" playbackRate: "Playback Speed" loop: "Loop playback" +_contextMenu: + title: "Context menu" + app: "Application" + appWithShift: "Application with shift key" + native: "Native" +_embedCodeGen: + title: "Customize embed code" + header: "Show header" + autoload: "Automatically load more (deprecated)" + maxHeight: "Max height" + maxHeightDescription: "Setting it to 0 disables the max height setting. Specify some value to prevent the widget from continuing to expand vertically." + maxHeightWarn: "The max height limit is disabled (0). If this was not intended, set the max height to some value." + previewIsNotActual: "The display differs from the actual embedding because it exceeds the range displayed on the preview screen." + rounded: "Make it rounded" + border: "Add a border to the outer frame" + applyToPreview: "Apply to the preview" + generateCode: "Generate embed code" + codeGenerated: "The code has been generated" + codeGeneratedDescription: "Paste the generated code into your website to embed the content." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 5c8249ded5..d574999e40 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -60,6 +60,7 @@ copyFileId: "Copiar ID del archivo" copyFolderId: "Copiar ID de carpeta" copyProfileUrl: "Copiar la URL del perfil" searchUser: "Buscar un usuario" +searchThisUsersNotes: "" reply: "Responder" loadMore: "Ver más" showMore: "Ver más" @@ -108,11 +109,14 @@ enterEmoji: "Ingresar emojis" renote: "Renotar" unrenote: "Quitar renota" renoted: "Renotado" +renotedToX: "{name} usuarios han renotado。" cantRenote: "No se puede renotar este post" cantReRenote: "No se puede renotar una renota" quote: "Citar" inChannelRenote: "Renota sólo del canal" inChannelQuote: "Cita sólo del canal" +renoteToChannel: "Renotar a otro canal" +renoteToOtherChannel: "Renotar a otro canal" pinnedNote: "Nota fijada" pinned: "Fijar al perfil" you: "Tú" @@ -151,6 +155,7 @@ editList: "Editar lista" selectChannel: "Seleccionar canal" selectAntenna: "Seleccionar antena" editAntenna: "Editar antena" +createAntenna: "Crear una antena" selectWidget: "Seleccionar widget" editWidgets: "Editar widgets" editWidgetsExit: "Terminar edición" @@ -177,6 +182,10 @@ addAccount: "Agregar Cuenta" reloadAccountsList: "Recargar lista de cuentas" loginFailed: "Error al iniciar sesión." showOnRemote: "Ver en una instancia remota" +continueOnRemote: "Ver en una instancia remota" +chooseServerOnMisskeyHub: "Elegir un servidor en Misskey Hub" +specifyServerHost: "Especifica una instancia directamente" +inputHostName: "Introduzca el dominio" general: "General" wallpaper: "Fondo de pantalla" setWallpaper: "Establecer fondo de pantalla" @@ -302,7 +311,7 @@ location: "Lugar" theme: "Tema" themeForLightMode: "Tema para usar en Modo Linterna" themeForDarkMode: "Tema para usar en Modo Oscuro" -light: "Linterna" +light: "Claro" dark: "Oscuro" lightThemes: "Tema claro" darkThemes: "Tema oscuro" @@ -493,7 +502,6 @@ uiLanguage: "Idioma de visualización de la interfaz" aboutX: "Acerca de {x}" emojiStyle: "Estilo de emoji" native: "Nativo" -disableDrawer: "No mostrar los menús en cajones" showNoteActionsOnlyHover: "Mostrar acciones de la nota sólo al pasar el cursor" showReactionsCount: "Mostrar el número de reacciones en las notas" noHistory: "No hay datos en el historial" @@ -692,10 +700,7 @@ abuseReported: "Se ha enviado el reporte. Muchas gracias." reporter: "Reportador" reporteeOrigin: "Reportar a" reporterOrigin: "Origen del reporte" -forwardReport: "Transferir un informe a una instancia remota" -forwardReportIsAnonymous: "No puede ver su información de la instancia remota y aparecerá como una cuenta anónima del sistema" send: "Enviar" -abuseMarkAsResolved: "Marcar reporte como resuelto" openInNewTab: "Abrir en una Nueva Pestaña" openInSideView: "Abrir en una vista al costado" defaultNavigationBehaviour: "Navegación por defecto" @@ -1094,6 +1099,8 @@ preservedUsernames: "Nombre de usuario reservado" preservedUsernamesDescription: "La lista de nombres de usuario para reservar tienen que separarse con saltos de línea.\nEstos estarán indisponibles durante la creación de cuentas, pero pueden ser usados para que los administradores puedan crear esas cuentas manualmente. Las cuentas existentes con esos nombres de usuario no se verán afectadas." createNoteFromTheFile: "Componer una nota desde éste archivo" archive: "Archivo" +archived: "Archivado" +unarchive: "Desarchivar" channelArchiveConfirmTitle: "¿Seguro de archivar {name}?" channelArchiveConfirmDescription: "Un canal archivado no aparecerá en la lista de canales ni en los resultados. Las nuevas publicaciones tampoco serán añadidas." thisChannelArchived: "El canal ha sido archivado." @@ -1908,7 +1915,6 @@ _theme: buttonBg: "Fondo de botón" buttonHoverBg: "Fondo de botón (hover)" inputBorder: "Borde de los campos de entrada" - listItemHoverBg: "Fondo de elemento de listas (hover)" driveFolderBg: "Fondo de capeta del drive" wallpaperOverlay: "Transparencia del fondo de pantalla" badge: "Medalla" @@ -1920,8 +1926,6 @@ _sfx: note: "Notas" noteMy: "Nota (a mí mismo)" notification: "Notificaciones" - antenna: "Antena receptora" - channel: "Notificaciones del canal" reaction: "Al seleccionar una reacción" _soundSettings: driveFile: "Usar un archivo de audio en Drive" @@ -2335,6 +2339,7 @@ _notification: followRequestAccepted: "El seguimiento fue aceptado" roleAssigned: "Rol asignado" achievementEarned: "Logro desbloqueado" + login: "Iniciar sesión" app: "Notificaciones desde aplicaciones" _actions: followBack: "Te sigue de vuelta" @@ -2384,7 +2389,6 @@ _webhookSettings: createWebhook: "Crear Webhook" name: "Nombre" secret: "Secreto" - events: "Eventos de webhook" active: "Activado" _events: follow: "Cuando se sigue a alguien" @@ -2394,6 +2398,12 @@ _webhookSettings: renote: "Cuando reciba un \"re-note\"" reaction: "Cuando se recibe una reacción" mention: "Cuando hay una mención" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Correo" + webhook: "Webhook" + keywords: "Palabras Clave" _moderationLogTypes: createRole: "Rol creado" deleteRole: "Rol eliminado" @@ -2497,6 +2507,7 @@ _hemisphere: S: "Hemisferio sur" _reversi: reversi: "Reversi" + rules: "Reglas" won: "{name} ha ganado" total: "Total" _urlPreviewSetting: diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 8d66c3d375..a7060c06fc 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -493,7 +493,6 @@ uiLanguage: "Langue d’affichage de l’interface" aboutX: "À propos de {x}" emojiStyle: "Style des émojis" native: "Natif" -disableDrawer: "Les menus ne s'affichent pas dans le tiroir" showNoteActionsOnlyHover: "Afficher les actions de note uniquement au survol" showReactionsCount: "Afficher le nombre de réactions des notes" noHistory: "Pas d'historique" @@ -692,10 +691,7 @@ abuseReported: "Le rapport est envoyé. Merci." reporter: "Signalé par" reporteeOrigin: "Origine du signalement" reporterOrigin: "Signalé par" -forwardReport: "Transférer le signalement à l’instance distante" -forwardReportIsAnonymous: "L'instance distante ne sera pas en mesure de voir vos informations et apparaîtra comme un compte anonyme du système." send: "Envoyer" -abuseMarkAsResolved: "Marquer le signalement comme résolu" openInNewTab: "Ouvrir dans un nouvel onglet" openInSideView: "Ouvrir en vue latérale" defaultNavigationBehaviour: "Navigation par défaut" @@ -1094,6 +1090,8 @@ preservedUsernames: "Noms d'utilisateur·rice réservés" preservedUsernamesDescription: "Énumérez les noms d'utilisateur à réserver, séparés par des nouvelles lignes. Les noms d'utilisateur spécifiés ici ne seront plus utilisables lors de la création d'un compte, sauf la création manuelle par un administrateur. De plus, les comptes existants ne seront pas affectés." createNoteFromTheFile: "Rédiger une note de ce fichier" archive: "Archive" +archived: "Archivé" +unarchive: "Annuler l'archivage" channelArchiveConfirmTitle: "Voulez-vous vraiment archiver {name} ?" channelArchiveConfirmDescription: "Une fois archivé, le canal n'apparaîtra plus dans la liste des canaux ni dans les résultats de recherche, et la publication des nouvelles notes sera impossible." thisChannelArchived: "Ce canal a été archivé." @@ -1224,7 +1222,10 @@ enableHorizontalSwipe: "Glisser pour changer d'onglet" loading: "Chargement en cours" surrender: "Annuler" gameRetry: "Réessayer" +launchApp: "Lancer l'app" +inquiry: "Contact" _delivery: + status: "Statut de la diffusion" stop: "Suspendu·e" _type: none: "Publié" @@ -1700,7 +1701,6 @@ _theme: buttonBg: "Arrière-plan du bouton" buttonHoverBg: "Arrière-plan du bouton (survolé)" inputBorder: "Cadre de la zone de texte" - listItemHoverBg: "Arrière-plan d'item de liste (survolé)" driveFolderBg: "Arrière-plan du dossier de disque" wallpaperOverlay: "Superposition de fond d'écran" badge: "Badge" @@ -1712,8 +1712,6 @@ _sfx: note: "Nouvelle note" noteMy: "Ma note" notification: "Notifications" - antenna: "Réception de l’antenne" - channel: "Notifications de canal" reaction: "Lors de la sélection de la réaction" _soundSettings: driveFile: "Utiliser un effet sonore sur le Disque" @@ -2035,6 +2033,7 @@ _notification: followRequestAccepted: "Demande d'abonnement acceptée" roleAssigned: "Rôle reçu" achievementEarned: "Déverrouillage d'accomplissement" + login: "Se connecter" app: "Notifications provenant des apps" _actions: followBack: "Suivre" @@ -2073,6 +2072,10 @@ _drivecleaner: _webhookSettings: name: "Nom" active: "Activé" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "E-mail " _moderationLogTypes: createRole: "Rôle créé" deleteRole: "Rôle supprimé" diff --git a/locales/hu-HU.yml b/locales/hu-HU.yml index 023a91494d..acc27ed092 100644 --- a/locales/hu-HU.yml +++ b/locales/hu-HU.yml @@ -96,6 +96,7 @@ _notification: renote: "Renote" quote: "Idézet" reaction: "Reakciók" + login: "Bejelentkezés" _actions: renote: "Renote" _deck: diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 7f509afa50..ce3958b167 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -60,6 +60,7 @@ copyFileId: "Salin Berkas" copyFolderId: "Salin Folder" copyProfileUrl: "Salin Alamat Web Profil" searchUser: "Cari pengguna" +searchThisUsersNotes: "Mencari catatan pengguna" reply: "Balas" loadMore: "Selebihnya" showMore: "Selebihnya" @@ -154,6 +155,7 @@ editList: "Sunting daftar" selectChannel: "Pilih kanal" selectAntenna: "Pilih Antena" editAntenna: "Sunting antena" +createAntenna: "Membuat antena." selectWidget: "Pilih gawit" editWidgets: "Sunting gawit" editWidgetsExit: "Selesai" @@ -180,6 +182,10 @@ addAccount: "Tambahkan akun" reloadAccountsList: "Muat ulang daftar akun" loginFailed: "Gagal untuk masuk" showOnRemote: "Lihat profil asli" +continueOnRemote: "Lihat di peladen asal" +chooseServerOnMisskeyHub: "Pilih peladen dari Misskey Hub" +specifyServerHost: "Tentukan domain peladen" +inputHostName: "Masukkan nama domain" general: "Umum" wallpaper: "Wallpaper" setWallpaper: "Atur wallpaper" @@ -316,6 +322,7 @@ selectFile: "Pilih berkas" selectFiles: "Pilih berkas" selectFolder: "Pilih folder" selectFolders: "Pilih folder" +fileNotSelected: "Tidak ada file yang dipilih" renameFile: "Ubah nama berkas" folderName: "Nama folder" createFolder: "Buat folder" @@ -497,7 +504,6 @@ uiLanguage: "Bahasa antarmuka pengguna" aboutX: "Tentang {x}" emojiStyle: "Gaya emoji" native: "Native" -disableDrawer: "Jangan gunakan menu bergaya laci" showNoteActionsOnlyHover: "Hanya tampilkan aksi catatan saat ditunjuk" showReactionsCount: "Lihat jumlah reaksi dalam catatan" noHistory: "Tidak ada riwayat" @@ -696,10 +702,7 @@ abuseReported: "Laporan kamu telah dikirimkan. Terima kasih." reporter: "Pelapor" reporteeOrigin: "Yang dilaporkan" reporterOrigin: "Pelapor" -forwardReport: "Teruskan laporan ke instansi luar" -forwardReportIsAnonymous: "Untuk melindungi privasi akun kamu, akun anonim dari sistem akan digunakan sebagai pelapor pada instansi luar." send: "Kirim" -abuseMarkAsResolved: "Tandai laporan sebagai selesai" openInNewTab: "Buka di tab baru" openInSideView: "Buka di tampilan samping" defaultNavigationBehaviour: "Navigasi bawaan" @@ -1239,6 +1242,7 @@ keepOriginalFilenameDescription: "Apabila pengaturan ini dimatikan, nama berkas noDescription: "Tidak ada deskripsi" alwaysConfirmFollow: "Selalu konfirmasi ketika mengikuti" inquiry: "Hubungi kami" +tryAgain: "Silahkan coba lagi." _delivery: status: "Status pengiriman" stop: "Ditangguhkan" @@ -1739,7 +1743,7 @@ _emailUnavailable: smtp: "Peladen alamat surel ini tidak merespon" banned: "Kamu tidak dapat mendaftar dengan alamat surel ini" _ffVisibility: - public: "Terbitkan" + public: "Publik" followers: "Tampil untuk pengikut saja" private: "Tersembunyi" _signup: @@ -1920,7 +1924,6 @@ _theme: buttonBg: "Latar belakang tombol" buttonHoverBg: "Latar belakang tombol (Mengambang)" inputBorder: "Batas bidang masukan" - listItemHoverBg: "Latar belakang daftar item (Mengambang)" driveFolderBg: "Latar belakang folder drive" wallpaperOverlay: "Lapisan wallpaper" badge: "Lencana" @@ -1932,8 +1935,6 @@ _sfx: note: "Catatan" noteMy: "Catatan (Saya)" notification: "Notifikasi" - antenna: "Penerimaan Antenna" - channel: "Notifikasi Kanal" reaction: "Ketika memilih reaksi" _soundSettings: driveFile: "Menggunakan berkas audio dalam Drive" @@ -2349,6 +2350,7 @@ _notification: followRequestAccepted: "Permintaan mengikuti disetujui" roleAssigned: "Peran Diberikan" achievementEarned: "Pencapaian didapatkan" + login: "Masuk" app: "Notifikasi dari aplikasi tertaut" _actions: followBack: "Ikuti Kembali" @@ -2396,9 +2398,9 @@ _drivecleaner: orderByCreatedAtAsc: "Tanggal (Naik)" _webhookSettings: createWebhook: "Buat Webhook" + modifyWebhook: "Sunting Webhook" name: "Nama" secret: "Secret" - events: "Webhook Events" active: "Aktif" _events: follow: "Ketika mengikuti pengguna" @@ -2408,6 +2410,11 @@ _webhookSettings: renote: "Ketika direnote" reaction: "Ketika menerima reaksi" mention: "Ketika sedang disebut" + deleteConfirm: "Apakah kamu yakin ingin menghapus Webhook?" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Surel" _moderationLogTypes: createRole: "Peran telah dibuat" deleteRole: "Peran telah dihapus" diff --git a/locales/index.d.ts b/locales/index.d.ts index acdc1fc421..2dca73bfa6 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -48,6 +48,20 @@ export interface Locale extends ILocale { * パスワード */ "password": string; + /** + * 初期設定開始用パスワード + */ + "initialPasswordForSetup": string; + /** + * 初期設定開始用のパスワードが違います。 + */ + "initialPasswordIsIncorrect": string; + /** + * Misskeyを自分でインストールした場合は、設定ファイルに入力したパスワードを使用してください。 + * Misskeyのホスティングサービスなどを使用している場合は、提供されたパスワードを使用してください。 + * パスワードを設定していない場合は、空欄にしたまま続行してください。 + */ + "initialPasswordForSetupDescription": string; /** * パスワードを忘れた */ @@ -256,6 +270,10 @@ export interface Locale extends ILocale { * ユーザーを検索 */ "searchUser": string; + /** + * ユーザーのノートを検索 + */ + "searchThisUsersNotes": string; /** * 返信 */ @@ -632,6 +650,10 @@ export interface Locale extends ILocale { * アンテナを編集 */ "editAntenna": string; + /** + * アンテナを作成 + */ + "createAntenna": string; /** * ウィジェットを選択 */ @@ -736,6 +758,22 @@ export interface Locale extends ILocale { * リモートで表示 */ "showOnRemote": string; + /** + * リモートで続行 + */ + "continueOnRemote": string; + /** + * Misskey Hubからサーバーを選択 + */ + "chooseServerOnMisskeyHub": string; + /** + * サーバーのドメインを直接指定 + */ + "specifyServerHost": string; + /** + * ドメインを入力してください + */ + "inputHostName": string; /** * 全般 */ @@ -776,6 +814,10 @@ export interface Locale extends ILocale { * ホスト */ "host": string; + /** + * 自分を選択 + */ + "selectSelf": string; /** * ユーザーを選択 */ @@ -836,6 +878,10 @@ export interface Locale extends ILocale { * サーバーをサイレンス */ "silenceThisInstance": string; + /** + * サーバーをメディアサイレンス + */ + "mediaSilenceThisInstance": string; /** * 操作 */ @@ -920,6 +966,22 @@ export interface Locale extends ILocale { * サイレンスしたいサーバーのホストを改行で区切って設定します。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになります。ブロックしたインスタンスには影響しません。 */ "silencedInstancesDescription": string; + /** + * メディアサイレンスしたサーバー + */ + "mediaSilencedInstances": string; + /** + * メディアサイレンスしたいサーバーのホストを改行で区切って設定します。メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われ、カスタム絵文字が使用できないようになります。ブロックしたインスタンスには影響しません。 + */ + "mediaSilencedInstancesDescription": string; + /** + * 連合を許可するサーバー + */ + "federationAllowedHosts": string; + /** + * 連合を許可するサーバーのホストを改行で区切って設定します。 + */ + "federationAllowedHostsDescription": string; /** * ミュートとブロック */ @@ -1312,6 +1374,10 @@ export interface Locale extends ILocale { * ファイルを追加 */ "addFile": string; + /** + * ファイルを表示 + */ + "showFile": string; /** * ドライブは空です */ @@ -1768,6 +1834,10 @@ export interface Locale extends ILocale { * モデレーションノート */ "moderationNote": string; + /** + * モデレーター間でだけ共有されるメモを記入することができます。 + */ + "moderationNoteDescription": string; /** * モデレーションノートを追加する */ @@ -1921,9 +1991,13 @@ export interface Locale extends ILocale { */ "onlyOneFileCanBeAttached": string; /** - * 続行する前に、サインアップまたはサインインが必要です + * 続行する前に、登録またはログインが必要です */ "signinRequired": string; + /** + * 続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があります + */ + "signinOrContinueOnRemote": string; /** * 招待 */ @@ -2009,9 +2083,21 @@ export interface Locale extends ILocale { */ "native": string; /** - * メニューをドロワーで表示しない + * メニューのスタイル */ - "disableDrawer": string; + "menuStyle": string; + /** + * スタイル + */ + "style": string; + /** + * ドロワー + */ + "drawer": string; + /** + * ポップアップ + */ + "popup": string; /** * ノートのアクションをホバー時のみ表示する */ @@ -2340,6 +2426,14 @@ export interface Locale extends ILocale { * スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。 */ "scratchpadDescription": string; + /** + * UIインスペクター + */ + "uiInspector": string; + /** + * メモリ上に存在しているUIコンポーネントのインスタンスの一覧を見ることができます。UIコンポーネントはUi:C:系関数により生成されます。 + */ + "uiInspectorDescription": string; /** * 出力 */ @@ -2785,7 +2879,7 @@ export interface Locale extends ILocale { */ "reportAbuseOf": ParameterizedString<"name">; /** - * 通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。 + * 通報理由の詳細を記入してください。対象のノートやページなどがある場合はそのURLも記入してください。 */ "fillAbuseReportDescription": string; /** @@ -2804,22 +2898,10 @@ export interface Locale extends ILocale { * 通報元 */ "reporterOrigin": string; - /** - * リモートサーバーに通報を転送する - */ - "forwardReport": string; - /** - * リモートサーバーからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。 - */ - "forwardReportIsAnonymous": string; /** * 送信 */ "send": string; - /** - * 対応済みにする - */ - "abuseMarkAsResolved": string; /** * 新しいタブで開く */ @@ -3077,7 +3159,7 @@ export interface Locale extends ILocale { */ "narrow": string; /** - * 設定はページリロード後に反映されます。今すぐリロードしますか? + * 設定はページリロード後に反映されます。 */ "reloadToApplySetting": string; /** @@ -3624,6 +3706,10 @@ export interface Locale extends ILocale { * パスワードが間違っています。 */ "incorrectPassword": string; + /** + * ワンタイムパスワードが間違っているか、期限切れになっています。 + */ + "incorrectTotp": string; /** * 「{choice}」に投票しますか? */ @@ -4420,6 +4506,14 @@ export interface Locale extends ILocale { * アーカイブ */ "archive": string; + /** + * アーカイブ済み + */ + "archived": string; + /** + * アーカイブ解除 + */ + "unarchive": string; /** * {name}をアーカイブしますか? */ @@ -4460,6 +4554,18 @@ export interface Locale extends ILocale { * ユーザー指定 */ "specifyUser": string; + /** + * 照会しますか? + */ + "lookupConfirm": string; + /** + * ハッシュタグのページを開きますか? + */ + "openTagPageConfirm": string; + /** + * ホスト指定 + */ + "specifyHost": string; /** * プレビューできません */ @@ -4984,6 +5090,113 @@ export interface Locale extends ILocale { * お問い合わせ */ "inquiry": string; + /** + * もう一度お試しください。 + */ + "tryAgain": string; + /** + * センシティブなメディアを表示するとき確認する + */ + "confirmWhenRevealingSensitiveMedia": string; + /** + * センシティブなメディアです。表示しますか? + */ + "sensitiveMediaRevealConfirm": string; + /** + * 作成したリスト + */ + "createdLists": string; + /** + * 作成したアンテナ + */ + "createdAntennas": string; + /** + * {x}から + */ + "fromX": ParameterizedString<"x">; + /** + * 埋め込みコードを生成 + */ + "genEmbedCode": string; + /** + * このユーザーのノート一覧 + */ + "noteOfThisUser": string; + /** + * これ以上このクリップにノートを追加できません。 + */ + "clipNoteLimitExceeded": string; + /** + * パフォーマンス + */ + "performance": string; + /** + * 変更あり + */ + "modified": string; + /** + * 破棄 + */ + "discard": string; + /** + * {n}件の変更があります + */ + "thereAreNChanges": ParameterizedString<"n">; + /** + * パスキーでログイン + */ + "signinWithPasskey": string; + /** + * 登録されていないパスキーです。 + */ + "unknownWebAuthnKey": string; + /** + * パスキーの検証に失敗しました。 + */ + "passkeyVerificationFailed": string; + /** + * パスキーの検証に成功しましたが、パスワードレスログインが無効になっています。 + */ + "passkeyVerificationSucceededButPasswordlessLoginDisabled": string; + /** + * フォロワーへのメッセージ + */ + "messageToFollower": string; + /** + * 対象 + */ + "target": string; + /** + * CAPTCHAのテストを目的とした機能です。本番環境で使用しないでください。 + */ + "testCaptchaWarning": string; + "_abuseUserReport": { + /** + * 転送 + */ + "forward": string; + /** + * 匿名のシステムアカウントとして、リモートサーバーに通報を転送します。 + */ + "forwardDescription": string; + /** + * 解決 + */ + "resolve": string; + /** + * 是認 + */ + "accept": string; + /** + * 否認 + */ + "reject": string; + /** + * 内容が正当である通報に対応した場合は「是認」を選択し、肯定的にケースが解決されたことをマークします。 + * 内容が正当でない通報の場合は「否認」を選択し、否定的にケースが解決されたことをマークします。 + */ + "resolveTutorial": string; + }; "_delivery": { /** * 配信状態 @@ -5475,6 +5688,10 @@ export interface Locale extends ILocale { * 有効にすると、タイムラインがキャッシュされていない場合にDBへ追加で問い合わせを行うフォールバック処理を行います。無効にすると、フォールバック処理を行わないことでさらにサーバーの負荷を軽減することができますが、タイムラインが取得できる範囲に制限が生じます。 */ "fanoutTimelineDbFallbackDescription": string; + /** + * 有効にすると、リアクション作成時のパフォーマンスが大幅に向上し、データベースへの負荷を軽減することが可能です。ただし、Redisのメモリ使用量は増加します。 + */ + "reactionsBufferingDescription": string; /** * 問い合わせ先URL */ @@ -5483,6 +5700,10 @@ export interface Locale extends ILocale { * サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定します。 */ "inquiryUrlDescription": string; + /** + * 一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。 + */ + "thisSettingWillAutomaticallyOffWhenModeratorsInactive": string; }; "_accountMigration": { /** @@ -6594,6 +6815,10 @@ export interface Locale extends ILocale { * ファイルにNSFWを常に付与 */ "alwaysMarkNsfw": string; + /** + * アイコンとバナーの更新を許可 + */ + "canUpdateBioMedia": string; /** * ノートのピン留めの最大数 */ @@ -6650,6 +6875,26 @@ export interface Locale extends ILocale { * アイコンデコレーションの最大取付個数 */ "avatarDecorationLimit": string; + /** + * アンテナのインポートを許可 + */ + "canImportAntennas": string; + /** + * ブロックのインポートを許可 + */ + "canImportBlocking": string; + /** + * フォローのインポートを許可 + */ + "canImportFollowing": string; + /** + * ミュートのインポートを許可 + */ + "canImportMuting": string; + /** + * リストのインポートを許可 + */ + "canImportUserLists": string; }; "_condition": { /** @@ -7468,10 +7713,6 @@ export interface Locale extends ILocale { * 入力ボックスの縁取り */ "inputBorder": string; - /** - * リスト項目の背景 (ホバー) - */ - "listItemHoverBg": string; /** * ドライブフォルダーの背景 */ @@ -7515,14 +7756,6 @@ export interface Locale extends ILocale { * 通知 */ "notification": string; - /** - * アンテナ受信 - */ - "antenna": string; - /** - * チャンネル通知 - */ - "channel": string; /** * リアクション選択時 */ @@ -7553,6 +7786,10 @@ export interface Locale extends ILocale { * 長い音声を使用するとMisskeyの使用に支障をきたす可能性があります。それでも続行しますか? */ "driveFileDurationWarnDescription": string; + /** + * 音声が読み込めませんでした。設定を変更してください + */ + "driveFileError": string; }; "_ago": { /** @@ -8545,6 +8782,18 @@ export interface Locale extends ILocale { * 最大{max}つまでデコレーションを付けられます。 */ "avatarDecorationMax": ParameterizedString<"max">; + /** + * フォローされた時のメッセージ + */ + "followedMessage": string; + /** + * フォローされた時に相手に表示する短いメッセージを設定できます。 + */ + "followedMessageDescription": string; + /** + * フォローを承認制にしている場合、フォローリクエストを許可した時に表示されます。 + */ + "followedMessageDescriptionForLockedAccount": string; }; "_exportOrImport": { /** @@ -8901,6 +9150,10 @@ export interface Locale extends ILocale { * ブロックを追加 */ "chooseBlock": string; + /** + * セクションタイトルを入力 + */ + "enterSectionTitle": string; /** * 種類を選択 */ @@ -9073,6 +9326,14 @@ export interface Locale extends ILocale { * 通知の履歴をリセットする */ "flushNotification": string; + /** + * {x}のエクスポートが完了しました + */ + "exportOfXCompleted": ParameterizedString<"x">; + /** + * ログインがありました + */ + "login": string; "_types": { /** * すべて @@ -9126,6 +9387,18 @@ export interface Locale extends ILocale { * 実績の獲得 */ "achievementEarned": string; + /** + * エクスポートが完了した + */ + "exportCompleted": string; + /** + * ログイン + */ + "login": string; + /** + * 通知のテスト + */ + "test": string; /** * 連携アプリからの通知 */ @@ -9318,9 +9591,9 @@ export interface Locale extends ILocale { */ "secret": string; /** - * Webhookを実行するタイミング + * トリガー */ - "events": string; + "trigger": string; /** * 有効 */ @@ -9364,11 +9637,19 @@ export interface Locale extends ILocale { * ユーザーからの通報を処理したとき */ "abuseReportResolved": string; + /** + * ユーザーが作成されたとき + */ + "userCreated": string; }; /** * Webhookを削除しますか? */ "deleteConfirm": string; + /** + * スイッチの右にあるボタンをクリックするとダミーのデータを使用したテスト用Webhookを送信できます。 + */ + "testRemarks": string; }; "_abuseReport": { "_notificationRecipient": { @@ -9531,6 +9812,14 @@ export interface Locale extends ILocale { * 通報を解決 */ "resolveAbuseReport": string; + /** + * 通報を転送 + */ + "forwardAbuseReport": string; + /** + * 通報のモデレーションノート更新 + */ + "updateAbuseReportNote": string; /** * 招待コードを作成 */ @@ -9591,6 +9880,22 @@ export interface Locale extends ILocale { * 通報の通知先を削除 */ "deleteAbuseReportNotificationRecipient": string; + /** + * アカウントを削除 + */ + "deleteAccount": string; + /** + * ページを削除 + */ + "deletePage": string; + /** + * Playを削除 + */ + "deleteFlash": string; + /** + * ギャラリーの投稿を削除 + */ + "deleteGalleryPost": string; }; "_fileViewer": { /** @@ -9761,7 +10066,7 @@ export interface Locale extends ILocale { "_dataSaver": { "_media": { /** - * メディアの読み込み + * メディアの読み込みを無効化 */ "title": string; /** @@ -9771,7 +10076,7 @@ export interface Locale extends ILocale { }; "_avatar": { /** - * アイコン画像 + * アイコン画像のアニメーションを無効化 */ "title": string; /** @@ -9781,7 +10086,7 @@ export interface Locale extends ILocale { }; "_urlPreview": { /** - * URLプレビューのサムネイル + * URLプレビューのサムネイルを非表示 */ "title": string; /** @@ -9791,7 +10096,7 @@ export interface Locale extends ILocale { }; "_code": { /** - * コードハイライト + * コードハイライトを非表示 */ "title": string; /** @@ -10066,6 +10371,78 @@ export interface Locale extends ILocale { */ "loop": string; }; + "_contextMenu": { + /** + * コンテキストメニュー + */ + "title": string; + /** + * アプリケーション + */ + "app": string; + /** + * Shiftキーでアプリケーション + */ + "appWithShift": string; + /** + * ブラウザのUI + */ + "native": string; + }; + "_embedCodeGen": { + /** + * 埋め込みコードをカスタマイズ + */ + "title": string; + /** + * ヘッダーを表示 + */ + "header": string; + /** + * 自動で続きを読み込む(非推奨) + */ + "autoload": string; + /** + * 高さの最大値 + */ + "maxHeight": string; + /** + * 0で最大値の設定が無効になります。ウィジェットが縦に伸び続けるのを防ぐために、何らかの値に指定してください。 + */ + "maxHeightDescription": string; + /** + * 高さの最大値制限が無効(0)になっています。これが意図した変更ではない場合は、高さの最大値を何らかの値に設定してください。 + */ + "maxHeightWarn": string; + /** + * プレビュー画面で表示可能な範囲を超えたため、実際に埋め込んだ際とは表示が異なります。 + */ + "previewIsNotActual": string; + /** + * 角丸にする + */ + "rounded": string; + /** + * 外枠に枠線をつける + */ + "border": string; + /** + * プレビューに反映 + */ + "applyToPreview": string; + /** + * 埋め込みコードを作成 + */ + "generateCode": string; + /** + * コードが生成されました + */ + "codeGenerated": string; + /** + * 生成されたコードをウェブサイトに貼り付けてご利用ください。 + */ + "codeGeneratedDescription": string; + }; } declare const locales: { [lang: string]: Locale; diff --git a/locales/index.js b/locales/index.js index 650e552337..c2738884eb 100644 --- a/locales/index.js +++ b/locales/index.js @@ -52,7 +52,11 @@ const primaries = { const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), ''); export function build() { - const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {}); + // vitestの挙動を調整するため、一度ローカル変数化する必要がある + // https://github.com/vitest-dev/vitest/issues/3988#issuecomment-1686599577 + // https://github.com/misskey-dev/misskey/pull/14057#issuecomment-2192833785 + const metaUrl = import.meta.url; + const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, metaUrl), 'utf-8'))) || {}, a), {}); // 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す const removeEmpty = (obj) => { diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 1d12a62cca..d42fff326c 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1,6 +1,6 @@ --- _lang_: "Italiano" -headlineMisskey: "Rete collegata tramite note" +headlineMisskey: "Rete collegata tramite Note" introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n\n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n\n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n\n🚀 Esplora un nuovo mondo insieme a noi!" poweredByMisskeyDescription: "{name} è uno dei servizi (chiamati istanze) che utilizzano la piattaforma open source Misskey." monthAndDay: "{day}/{month}" @@ -8,6 +8,9 @@ search: "Cerca" notifications: "Notifiche" username: "Nome utente" password: "Password" +initialPasswordForSetup: "Password iniziale, per avviare le impostazioni" +initialPasswordIsIncorrect: "Password iniziale, sbagliata." +initialPasswordForSetupDescription: "Se hai installato Misskey di persona, usa la password che hai indicato nel file di configurazione.\nSe stai utilizzando un servizio di hosting Misskey, usa la password fornita dal gestore.\nSe non hai una password preimpostata, lascia il campo vuoto e continua." forgotPassword: "Hai dimenticato la password?" fetchingAsApObject: "Recuperando dal Fediverso..." ok: "OK" @@ -60,6 +63,7 @@ copyFileId: "Copia ID del file" copyFolderId: "Copia ID della cartella" copyProfileUrl: "Copia URL del profilo" searchUser: "Cerca profilo" +searchThisUsersNotes: "Cerca le sue Note" reply: "Rispondi" loadMore: "Mostra di più" showMore: "Espandi" @@ -108,11 +112,14 @@ enterEmoji: "Inserisci emoji" renote: "Rinota" unrenote: "Elimina la Rinota" renoted: "Rinotata!" +renotedToX: "Rinota da {name}." cantRenote: "È impossibile rinotare questa nota." cantReRenote: "È impossibile rinotare una Rinota." quote: "Citazione" inChannelRenote: "Rinota nel canale" inChannelQuote: "Cita nel canale" +renoteToChannel: "Rinota al canale" +renoteToOtherChannel: "Rinota a un altro canale" pinnedNote: "Nota in primo piano" pinned: "Fissa sul profilo" you: "Tu" @@ -151,6 +158,7 @@ editList: "Modifica Lista" selectChannel: "Seleziona canale" selectAntenna: "Scegli un'antenna" editAntenna: "Modifica Antenna" +createAntenna: "Crea Antenna" selectWidget: "Seleziona il riquadro" editWidgets: "Modifica i riquadri" editWidgetsExit: "Conferma le modifiche" @@ -177,6 +185,10 @@ addAccount: "Aggiungi profilo" reloadAccountsList: "Ricarica l'elenco dei profili" loginFailed: "Accesso non riuscito" showOnRemote: "Leggi sull'istanza remota" +continueOnRemote: "Continua da remoto" +chooseServerOnMisskeyHub: "Scegli l'istanza sul sito Misskey Hub" +specifyServerHost: "Indica l'indirizzo dell'istanza" +inputHostName: "Digita il nome del dominio " general: "Generali" wallpaper: "Sfondo" setWallpaper: "Imposta sfondo" @@ -187,6 +199,7 @@ followConfirm: "Vuoi seguire {name}?" proxyAccount: "Profilo proxy" proxyAccountDescription: "Un profilo proxy funziona come follower per i profili remoti, sotto certe condizioni. Ad esempio, quando un profilo locale ne inserisce uno remoto in una lista (senza seguirlo), se nessun altro segue quel profilo remoto, le attività non possono essere distribuite. Dunque, il profilo proxy le seguirà per tutti." host: "Host" +selectSelf: "Segli me" selectUser: "Seleziona profilo" recipient: "Destinatario" annotation: "Annotazione preventiva" @@ -202,6 +215,7 @@ perDay: "giornaliero" stopActivityDelivery: "Interrompi la distribuzione di attività" blockThisInstance: "Bloccare l'istanza" silenceThisInstance: "Silenziare l'istanza" +mediaSilenceThisInstance: "Silenzia i media dell'istanza" operations: "Operazioni" software: "Software" version: "Versione" @@ -223,6 +237,10 @@ blockedInstances: "Istanze bloccate" blockedInstancesDescription: "Elenca le istanze che vuoi bloccare, una per riga. Esse non potranno più interagire con la tua istanza." silencedInstances: "Istanze silenziate" silencedInstancesDescription: "Elenca i nomi host delle istanze che vuoi silenziare. Tutti i profili nelle istanze silenziate vengono trattati come tali. Possono solo inviare richieste di follow e menzionare soltanto i profili locali che seguono. Le istanze bloccate non sono interessate." +mediaSilencedInstances: "Istanze coi media silenziati" +mediaSilencedInstancesDescription: "Elenca i nomi host delle istanze di cui vuoi silenziare i media, uno per riga. Tutti gli allegati dei profili nelle istanze silenziate per via degli allegati espliciti, verranno impostati come tali, le emoji personalizzate non saranno disponibili. Le istanze bloccate sono escluse." +federationAllowedHosts: "Server a cui consentire la federazione" +federationAllowedHostsDescription: "Indica gli host dei server a cui è consentita la federazione, uno per ogni linea." muteAndBlock: "Silenziare e bloccare" mutedUsers: "Profili silenziati" blockedUsers: "Profili bloccati" @@ -313,6 +331,7 @@ selectFile: "Scelta allegato" selectFiles: "Scelta allegato" selectFolder: "Seleziona cartella" selectFolders: "Seleziona cartella" +fileNotSelected: "Nessun file selezionato" renameFile: "Rinomina file" folderName: "Nome della cartella" createFolder: "Nuova cartella" @@ -320,6 +339,7 @@ renameFolder: "Rinomina cartella" deleteFolder: "Elimina cartella" folder: "Cartella" addFile: "Allega" +showFile: "Visualizza file" emptyDrive: "Il Drive è vuoto" emptyFolder: "La cartella è vuota" unableToDelete: "Eliminazione impossibile" @@ -441,7 +461,7 @@ securityKeyAndPasskey: "Chiave di sicurezza e accesso" securityKey: "Chiave di sicurezza" lastUsed: "Ultima attività" lastUsedAt: "Uso più recente: {t}" -unregister: "Annulla l'iscrizione" +unregister: "Rimuovi autenticazione a due fattori (2FA/MFA)" passwordLessLogin: "Accedi senza password" passwordLessLoginDescription: "Accedi senza password, usando la chiave di sicurezza" resetPassword: "Ripristina la password" @@ -468,10 +488,12 @@ retype: "Conferma" noteOf: "Note di {user}" quoteAttached: "Citazione allegata" quoteQuestion: "Vuoi aggiungere una citazione?" +attachAsFileQuestion: "Il testo copiato eccede le dimensioni, vuoi allegarlo?" noMessagesYet: "Ancora nessuna chat" newMessageExists: "Hai ricevuto un nuovo messaggio" onlyOneFileCanBeAttached: "È possibile allegare al messaggio soltanto uno file" signinRequired: "Occorre avere un profilo registrato su questa istanza" +signinOrContinueOnRemote: "Per continuare, devi accedere alla tua istanza o registrarti su questa e poi accedere" invitations: "Invita" invitationCode: "Codice di invito" checking: "Confermando" @@ -493,7 +515,10 @@ uiLanguage: "Lingua di visualizzazione dell'interfaccia" aboutX: "Informazioni su {x}" emojiStyle: "Stile emoji" native: "Nativo" -disableDrawer: "Non mostrare il menù sul drawer" +menuStyle: "Stile menu" +style: "Stile" +drawer: "Drawer" +popup: "Popup" showNoteActionsOnlyHover: "Mostra le azioni delle Note solo al passaggio del mouse" showReactionsCount: "Visualizza il numero di reazioni su una nota" noHistory: "Nessuna cronologia" @@ -549,7 +574,7 @@ deleteAll: "Cancella cronologia" showFixedPostForm: "Visualizzare la finestra di pubblicazione in cima alla timeline" showFixedPostFormInChannel: "Per i canali, mostra il modulo di pubblicazione in cima alla timeline" withRepliesByDefaultForNewlyFollowed: "Quando segui nuovi profili, includi le risposte in TL come impostazione predefinita" -newNoteRecived: "Nuove note da leggere" +newNoteRecived: "Nuove Note da leggere" sounds: "Impostazioni suoni" sound: "Suono" listen: "Ascolta" @@ -576,6 +601,8 @@ ascendingOrder: "Aumenta" descendingOrder: "Diminuisce" scratchpad: "ScratchPad" scratchpadDescription: "Lo Scratchpad offre un ambiente per esperimenti di AiScript. È possibile scrivere, eseguire e confermare i risultati dell'interazione del codice con Misskey." +uiInspector: "UI Inspector" +uiInspectorDescription: "Puoi visualizzare un elenco di elementi UI presenti in memoria. I componenti dell'interfaccia utente vengono generati dalle funzioni Ui:C:." output: "Uscita" script: "Script" disablePagesScript: "Disabilita AiScript nelle pagine" @@ -692,10 +719,7 @@ abuseReported: "La segnalazione è stata inviata. Grazie." reporter: "il corrispondente" reporteeOrigin: "Segnalazione a" reporterOrigin: "Segnalazione da" -forwardReport: "Inoltro di un report a un'istanza remota." -forwardReportIsAnonymous: "L'istanza remota non vedrà le tue informazioni, apparirai come profilo di sistema, anonimo." send: "Inviare" -abuseMarkAsResolved: "Contrassegna la segnalazione come risolta" openInNewTab: "Apri in una nuova scheda" openInSideView: "Apri in vista laterale" defaultNavigationBehaviour: "Navigazione preimpostata" @@ -832,6 +856,7 @@ administration: "Gestione" accounts: "Profilo" switch: "Cambia" noMaintainerInformationWarning: "Mancano le informazioni sull'amministratore." +noInquiryUrlWarning: "Non è stata impostata la URL di contatto" noBotProtectionWarning: "Non è stata impostata alcuna protezione dai Bot" configure: "Imposta" postToGallery: "Pubblicare nella galleria" @@ -896,6 +921,7 @@ followersVisibility: "Visibilità dei profili che ti seguono" continueThread: "Altre conversazioni" deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?" incorrectPassword: "La password è errata." +incorrectTotp: "Il codice OTP è sbagliato, oppure scaduto." voteConfirm: "Votare per「{choice}」?" hide: "Nascondere" useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile" @@ -1021,6 +1047,7 @@ thisPostMayBeAnnoyingHome: "Pubblica sulla timeline principale" thisPostMayBeAnnoyingCancel: "Annulla" thisPostMayBeAnnoyingIgnore: "Pubblica lo stesso" collapseRenotes: "Comprimi le Rinota già viste" +collapseRenotesDescription: "Comprimi le Note con cui hai già interagito." internalServerError: "Errore interno del server" internalServerErrorDescription: "Si è verificato un errore imprevisto all'interno del server" copyErrorInfo: "Copia le informazioni sull'errore" @@ -1094,6 +1121,8 @@ preservedUsernames: "Nomi utente riservati" preservedUsernamesDescription: "Elenca, uno per linea, i nomi utente che non possono essere registrati durante la creazione del profilo. La restrizione non si applica agli amministratori. Inoltre, i profili già registrati sono esenti." createNoteFromTheFile: "Crea Nota da questo file" archive: "Archivio" +archived: "Archiviato" +unarchive: "Annulla archiviazione" channelArchiveConfirmTitle: "Vuoi davvero archiviare {name}?" channelArchiveConfirmDescription: "Un canale archiviato non compare nell'elenco canali, nemmeno nei risultati di ricerca. Non può ricevere nemmeno nuove Note." thisChannelArchived: "Questo canale è stato archiviato." @@ -1104,6 +1133,9 @@ preventAiLearning: "Impedisci l'apprendimento della IA" preventAiLearningDescription: "Aggiungendo il campo \"noai\" alla risposta HTML, si indica ai Robot esterni di non usare testi e allegati per addestrare sistemi di Machine Learning (IA predittiva/generativa). Anche se è impossibile sapere se la richiesta venga onorata o semplicemente ignorata." options: "Opzioni del ruolo" specifyUser: "Profilo specifico" +lookupConfirm: "Vuoi davvero richiedere informazioni?" +openTagPageConfirm: "Vuoi davvero aprire la pagina dell'hashtag?" +specifyHost: "Specifica l'host" failedToPreviewUrl: "Anteprima non disponibile" update: "Aggiorna" rolesThatCanBeUsedThisEmojiAsReaction: "Ruoli che possono usare questa emoji come reazione" @@ -1233,10 +1265,35 @@ useNativeUIForVideoAudioPlayer: "Riprodurre audio/video usando le funzionalità keepOriginalFilename: "Mantieni il nome file originale" keepOriginalFilenameDescription: "Disattivandola, i file verranno caricati usando nomi casuali." noDescription: "Manca la descrizione" +alwaysConfirmFollow: "Richiedi conferma per i Follow" +inquiry: "Contattaci" +tryAgain: "Per favore riprova" +confirmWhenRevealingSensitiveMedia: "Richiedi conferma prima di mostrare gli allegati espliciti" +sensitiveMediaRevealConfirm: "Questo allegato è esplicito, vuoi vederlo?" +createdLists: "Liste create" +createdAntennas: "Antenne create" +fromX: "Da {x}" +genEmbedCode: "Ottieni il codice di incorporamento" +noteOfThisUser: "Elenco di Note di questo profilo" +clipNoteLimitExceeded: "Non è possibile aggiungere ulteriori Note a questa Clip." +performance: "Prestazioni" +modified: "Modificato" +discard: "Scarta" +thereAreNChanges: "Ci sono {n} cambiamenti" +signinWithPasskey: "Accedi con passkey" +unknownWebAuthnKey: "Questa è una passkey sconosciuta." +passkeyVerificationFailed: "La verifica della passkey non è riuscita." +passkeyVerificationSucceededButPasswordlessLoginDisabled: "La verifica della passkey è riuscita, ma l'accesso senza password è disabilitato." +messageToFollower: "Messaggio ai follower" _delivery: + status: "Stato della consegna" stop: "Sospensione" + resume: "Riprendi la consegna" _type: none: "Pubblicazione" + manuallySuspended: "Sospesa manualmente" + goneSuspended: "Sospensione server a causa dell'eliminazione" + autoSuspendedForNotResponding: "Sospensione del server a causa di mancata risposta" _bubbleGame: howToPlay: "Come giocare" hold: "Tieni" @@ -1282,7 +1339,7 @@ _initialAccountSetting: skipAreYouSure: "Vuoi davvero saltare la configurazione iniziale?" laterAreYouSure: "Vuoi davvero rimandare la configurazione iniziale?" _initialTutorial: - launchTutorial: "Guarda il tutorial" + launchTutorial: "Inizia il tutorial" title: "Tutorial" wellDone: "Ottimo lavoro!" skipAreYouSure: "Vuoi davvero interrompere il tutorial?" @@ -1292,13 +1349,13 @@ _initialTutorial: _note: title: "Cosa sono le Note?" description: "Gli status su Misskey sono chiamati \"Note\". Le Note sono elencate in ordine cronologico nelle timeline e vengono aggiornate in tempo reale." - reply: "Puoi rispondere alle Note. Puoi anche rispondere alle risposte e continuare i dialoghi come un conversazioni." - renote: "Puoi ri-condividere le Note, facendole rifluire sulla Timeline. Puoi anche aggiungere testo e citare altri profili." - reaction: "Puoi aggiungere una reazione. Nella pagina successiva spiegheremo i dettagli." - menu: "Puoi svolgere varie attività, come visualizzare i dettagli delle Note o copiare i collegamenti." + reply: "Puoi rispondere alle Note, alle altre risposte e dialogare in conversazioni." + renote: "Puoi ri-condividere le Note, ritorneranno sulla Timeline. Aggiungendo del testo, scriverai una Citazione." + reaction: "Puoi aggiungere una reazione. Nella pagina successiva ti spiego come." + menu: "Per altre attività, ad esempio, vedere i dettagli delle Note o copiare i collegamenti." _reaction: title: "Cosa sono le Reazioni?" - description: "Puoi reagire alle Note. Le sensazioni che non si riescono a trasmettere con i \"Mi piace\" si possono esprimere facilmente inviando una reazione." + description: "Reazioni alle Note. Le sensazioni che non si possono descrivere con \"Mi piace\" si esprimono facilmente con le reazioni." letsTryReacting: "Puoi aggiungere una Reazione cliccando il bottone \"+\" (più) della relativa Nota. Prova ad aggiungerne una a questa Nota di esempio!" reactToContinue: "Aggiungere la Reazione ti consentirà di procedere col tutorial." reactNotification: "Quando qualcuno reagisce alle tue Note, ricevi una notifica in tempo reale." @@ -1311,7 +1368,7 @@ _initialTutorial: social: "sia le Note della Timeline Home che quelle della Timeline Locale, insieme!" global: "le Note da pubblicate da tutte le altre istanze federate con la nostra." description2: "Nella parte superiore dello schermo, puoi scegliere una Timeline o l'altra in qualsiasi momento." - description3: "Ci sono anche sequenze temporali di elenchi, sequenze temporali di canali, ecc. Per ulteriori dettagli, consultare il {link}.\nPuoi vedere anche Timeline delle liste di profili (se ne hai create), canali, ecc... Per i dettagli, visita {link}." + description3: "Ci sono anche sequenze temporali di elenchi, sequenze temporali di canali, ecc. Per ulteriori dettagli, consultare la {link}.\nPuoi vedere anche Timeline delle liste di profili (se ne hai create), canali, ecc... Per i dettagli, c'è la {link}." _postNote: title: "La Nota e le sue impostazioni" description1: "Quando scrivi una Nota su Misskey, hai a disposizione varie opzioni. Il modulo di invio è simile a questo." @@ -1362,6 +1419,9 @@ _serverSettings: fanoutTimelineDescription: "Attivando questa funzionalità migliori notevolmente la capacità delle Timeline di collezionare Note, riducendo il carico sul database. Tuttavia, aumenterà l'impiego di memoria RAM per Redis. Disattiva se il tuo server ha poca RAM o la funzionalità è irregolare." fanoutTimelineDbFallback: "Elaborazione dati alternativa" fanoutTimelineDbFallbackDescription: "Attivando l'elaborazione alternativa, verrà interrogato ulteriormente il database se la timeline non è nella cache. \nDisattivando, si può ridurre ulteriormente il carico del server, evitando l'elaborazione alternativa, ma limitando l'intervallo recuperabile delle timeline." + reactionsBufferingDescription: "Attivando questa opzione, puoi migliorare significativamente le prestazioni durante la creazione delle reazioni e ridurre il carico sul database. Tuttavia, aumenterà l'impiego di memoria Redis." + inquiryUrl: "URL di contatto" + inquiryUrlDescription: "Specificare l'URL al modulo di contatto, oppure le informazioni con i dati di contatto dell'amministrazione." _accountMigration: moveFrom: "Migra un altro profilo dentro a questo" moveFromSub: "Crea un alias verso un altro profilo remoto" @@ -1678,6 +1738,7 @@ _role: canManageAvatarDecorations: "Gestisce le decorazioni di immagini del profilo" driveCapacity: "Capienza del Drive" alwaysMarkNsfw: "Impostare sempre come esplicito (NSFW)" + canUpdateBioMedia: "Può aggiornare foto profilo e di testata" pinMax: "Quantità massima di Note in primo piano" antennaMax: "Quantità massima di Antenne" wordMuteMax: "Lunghezza massima del filtro parole" @@ -1692,10 +1753,20 @@ _role: canSearchNotes: "Ricercare nelle Note" canUseTranslator: "Tradurre le Note" avatarDecorationLimit: "Numero massimo di decorazioni foto profilo installabili" + canImportAntennas: "Può importare Antenne" + canImportBlocking: "Può importare Blocchi" + canImportFollowing: "Può importare Following" + canImportMuting: "Può importare Silenziati" + canImportUserLists: "Può importare liste di Profili" _condition: roleAssignedTo: "Assegnato a ruoli manualmente" isLocal: "Profilo locale" isRemote: "Profilo remoto" + isCat: "È un gattino" + isBot: "È un bot" + isSuspended: "È sospeso" + isLocked: "È in stato privato" + isExplorable: "Autorizza la pubblicazione nei cataloghi" createdLessThan: "Profilo creato da meno di N" createdMoreThan: "Profilo creato da più di N" followersLessThanOrEq: "Profilo con N follower o meno" @@ -1904,7 +1975,6 @@ _theme: buttonBg: "Sfondo del pulsante" buttonHoverBg: "Sfondo del pulsante (sorvolato)" inputBorder: "Inquadra casella di testo" - listItemHoverBg: "Sfondo della voce di elenco (sorvolato)" driveFolderBg: "Sfondo della cartella di disco" wallpaperOverlay: "Sovrapposizione dello sfondo" badge: "Distintivo" @@ -1916,8 +1986,6 @@ _sfx: note: "Nota" noteMy: "Mia nota" notification: "Notifiche" - antenna: "Ricezione dell'antenna" - channel: "Notifiche di canale" reaction: "Quando seleziono una reazione" _soundSettings: driveFile: "Suoni del Drive" @@ -1926,6 +1994,7 @@ _soundSettings: driveFileTypeWarnDescription: "Per favore, scegli un file di tipo audio" driveFileDurationWarn: "La durata dell'audio è troppo lunga" driveFileDurationWarnDescription: "Scegliere un audio lungo potrebbe interferire con l'uso di Misskey. Vuoi continuare lo stesso?" + driveFileError: "Impossibile caricare l'audio. Si prega di modificare le impostazioni" _ago: future: "Futuro" justNow: "Adesso" @@ -2182,6 +2251,9 @@ _profile: changeBanner: "Cambia intestazione" verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo." avatarDecorationMax: "Puoi aggiungere fino a {max} decorazioni." + followedMessage: "Messaggio, quando qualcuno ti segue" + followedMessageDescription: "Puoi impostare un breve messaggio da mostrare agli altri profili quando ti seguono." + followedMessageDescriptionForLockedAccount: "Quando approvi una richiesta di follow, verrà visualizzato questo testo." _exportOrImport: allNotes: "Tutte le note" favoritedNotes: "Note preferite" @@ -2274,6 +2346,7 @@ _pages: eyeCatchingImageSet: "Imposta un'immagine attraente" eyeCatchingImageRemove: "Elimina immagine attraente" chooseBlock: "Aggiungi blocco" + enterSectionTitle: "Inserisci il titolo della sezione" selectType: "Seleziona tipo" contentBlocks: "Contenuto" inputBlocks: "Blocchi di input" @@ -2319,6 +2392,8 @@ _notification: renotedBySomeUsers: "{n} Rinota" followedBySomeUsers: "{n} follower" flushNotification: "Azzera le notifiche" + exportOfXCompleted: "Abbiamo completato l'esportazione di {x}" + login: "Autenticazione avvenuta" _types: all: "Tutto" note: "Nuove Note" @@ -2333,6 +2408,9 @@ _notification: followRequestAccepted: "Richiesta di follow accettata" roleAssigned: "Ruolo concesso" achievementEarned: "Risultato raggiunto" + exportCompleted: "Esportazione completata" + login: "Accedi" + test: "Prova la notifica" app: "Notifiche da applicazioni" _actions: followBack: "Segui" @@ -2342,6 +2420,7 @@ _deck: alwaysShowMainColumn: "Mostra sempre la colonna principale" columnAlign: "Allineare colonne" addColumn: "Aggiungi colonna" + newNoteNotificationSettings: "Preferenze per le notifiche di nuove Note" configureColumn: "Impostazioni colonna" swapLeft: "Sposta a sinistra" swapRight: "Sposta a destra" @@ -2380,9 +2459,10 @@ _drivecleaner: orderByCreatedAtAsc: "Dal più vecchio al più recente" _webhookSettings: createWebhook: "Creazione Webhook" + modifyWebhook: "Modifica Webhook" name: "Nome" secret: "Segreto" - events: "Quando eseguire il Webhook" + trigger: "Trigger" active: "Attivo" _events: follow: "Quando segui un profilo" @@ -2392,6 +2472,27 @@ _webhookSettings: renote: "Quando la Nota è Rinotata" reaction: "Quando ricevo una reazione" mention: "Quando mi menzionano" + _systemEvents: + abuseReport: "Quando arriva una segnalazione" + abuseReportResolved: "Quando una segnalazione è risolta" + userCreated: "Quando viene creato un profilo" + deleteConfirm: "Vuoi davvero eliminare il Webhook?" + testRemarks: "Clicca il bottone a destra dell'interruttore, per provare l'invio di un webhook con dati fittizi." +_abuseReport: + _notificationRecipient: + createRecipient: "Aggiungi destinatario della segnalazione" + modifyRecipient: "Modifica destinatario della segnalazione" + recipientType: "Tipo di notifica" + _recipientType: + mail: "Email" + webhook: "Webhook" + _captions: + mail: "Quando ricevi un abuso, notifica l'amministrazione via email" + webhook: "Spedire una notifica al SystemWebhook specificato (sia quando si riceve una segnalazione, che quando viene risolta)" + keywords: "Parole chiave" + notifiedUser: "Profili da notificare" + notifiedWebhook: "Webhook da usare" + deleteConfirm: "Vuoi davvero rimuovere il destinatario della notifica?" _moderationLogTypes: createRole: "Ruolo creato" deleteRole: "Ruolo eliminato" @@ -2429,6 +2530,16 @@ _moderationLogTypes: deleteAvatarDecoration: "Eliminazione decorazione della foto profilo" unsetUserAvatar: "Rimossa foto profilo" unsetUserBanner: "Rimossa intestazione profilo" + createSystemWebhook: "Crea un SystemWebhook" + updateSystemWebhook: "Modifica SystemWebhook" + deleteSystemWebhook: "Elimina SystemWebhook" + createAbuseReportNotificationRecipient: "Crea destinatario per le notifiche di segnalazioni" + updateAbuseReportNotificationRecipient: "Aggiorna destinatario notifiche di segnalazioni" + deleteAbuseReportNotificationRecipient: "Elimina destinatario notifiche di segnalazioni" + deleteAccount: "Quando viene eliminato un profilo" + deletePage: "Pagina eliminata" + deleteFlash: "Play eliminato" + deleteGalleryPost: "Eliminazione pubblicazione nella Galleria" _fileViewer: title: "Dettagli del file" type: "Tipo di file" @@ -2554,7 +2665,28 @@ _urlPreviewSetting: userAgent: "User-Agent" userAgentDescription: "Definire con quale User-Agent si intende identificarsi durante l'acquisizione di un'anteprima. Se è vuoto, useremo il valore predefinito." summaryProxy: "Endpoint proxy che genera l'anteprima" + summaryProxyDescription: "Genera anteprime utilizzando un proxy Summaly anziché Misskey." + summaryProxyDescription2: "I parametri sono collegano al proxy come stringa query. Se il proxy non li supporta, verranno ignorati." _mediaControls: pip: "Sovraimpressione" playbackRate: "Velocità di riproduzione" loop: "Ripetizione infinita" +_contextMenu: + title: "Menu contestuale" + app: "Applicazione" + appWithShift: "Applicazione Shift+Tasto" + native: "Interfaccia utente del browser" +_embedCodeGen: + title: "Personalizza il codice di incorporamento" + header: "Mostra la testata" + autoload: "Carica automaticamente di più (sconsigliato)" + maxHeight: "Altezza massima" + maxHeightDescription: "Specifica un valore per evitare che continui a crescere verticalmente. Il valore 0 disabilita il limite d'altezza." + maxHeightWarn: "L'altezza massima è disabilitata (0). Se l'effetto è indesiderato, prova a impostare l'altezza massima a un valore specifico." + previewIsNotActual: "Poiché supera l'intervallo che può essere visualizzato in anteprima, la visualizzazione vera e propria sarà diversa quando effettivamente incorporata." + rounded: "Bordo arrotondato" + border: "Aggiungi un bordo al contenitore" + applyToPreview: "Applica all'anteprima" + generateCode: "Crea il codice di incorporamento" + codeGenerated: "Codice generato" + codeGeneratedDescription: "Incolla il codice appena generato sul tuo sito web." diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0d89d33abe..440ffa9306 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -8,6 +8,9 @@ search: "検索" notifications: "通知" username: "ユーザー名" password: "パスワード" +initialPasswordForSetup: "初期設定開始用パスワード" +initialPasswordIsIncorrect: "初期設定開始用のパスワードが違います。" +initialPasswordForSetupDescription: "Misskeyを自分でインストールした場合は、設定ファイルに入力したパスワードを使用してください。\nMisskeyのホスティングサービスなどを使用している場合は、提供されたパスワードを使用してください。\nパスワードを設定していない場合は、空欄にしたまま続行してください。" forgotPassword: "パスワードを忘れた" fetchingAsApObject: "連合に照会中" ok: "OK" @@ -60,6 +63,7 @@ copyFileId: "ファイルIDをコピー" copyFolderId: "フォルダーIDをコピー" copyProfileUrl: "プロフィールURLをコピー" searchUser: "ユーザーを検索" +searchThisUsersNotes: "ユーザーのノートを検索" reply: "返信" loadMore: "もっと見る" showMore: "もっと見る" @@ -154,6 +158,7 @@ editList: "リストを編集" selectChannel: "チャンネルを選択" selectAntenna: "アンテナを選択" editAntenna: "アンテナを編集" +createAntenna: "アンテナを作成" selectWidget: "ウィジェットを選択" editWidgets: "ウィジェットを編集" editWidgetsExit: "編集を終了" @@ -180,6 +185,10 @@ addAccount: "アカウントを追加" reloadAccountsList: "アカウントリストの情報を更新" loginFailed: "ログインに失敗しました" showOnRemote: "リモートで表示" +continueOnRemote: "リモートで続行" +chooseServerOnMisskeyHub: "Misskey Hubからサーバーを選択" +specifyServerHost: "サーバーのドメインを直接指定" +inputHostName: "ドメインを入力してください" general: "全般" wallpaper: "壁紙" setWallpaper: "壁紙を設定" @@ -190,6 +199,7 @@ followConfirm: "{name}をフォローしますか?" proxyAccount: "プロキシアカウント" proxyAccountDescription: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。" host: "ホスト" +selectSelf: "自分を選択" selectUser: "ユーザーを選択" recipient: "宛先" annotation: "注釈" @@ -205,6 +215,7 @@ perDay: "1日ごと" stopActivityDelivery: "アクティビティの配送を停止" blockThisInstance: "このサーバーをブロック" silenceThisInstance: "サーバーをサイレンス" +mediaSilenceThisInstance: "サーバーをメディアサイレンス" operations: "操作" software: "ソフトウェア" version: "バージョン" @@ -226,6 +237,10 @@ blockedInstances: "ブロックしたサーバー" blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定します。ブロックされたサーバーは、このインスタンスとやり取りできなくなります。" silencedInstances: "サイレンスしたサーバー" silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定します。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになります。ブロックしたインスタンスには影響しません。" +mediaSilencedInstances: "メディアサイレンスしたサーバー" +mediaSilencedInstancesDescription: "メディアサイレンスしたいサーバーのホストを改行で区切って設定します。メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われ、カスタム絵文字が使用できないようになります。ブロックしたインスタンスには影響しません。" +federationAllowedHosts: "連合を許可するサーバー" +federationAllowedHostsDescription: "連合を許可するサーバーのホストを改行で区切って設定します。" muteAndBlock: "ミュートとブロック" mutedUsers: "ミュートしたユーザー" blockedUsers: "ブロックしたユーザー" @@ -324,6 +339,7 @@ renameFolder: "フォルダー名を変更" deleteFolder: "フォルダーを削除" folder: "フォルダー" addFile: "ファイルを追加" +showFile: "ファイルを表示" emptyDrive: "ドライブは空です" emptyFolder: "フォルダーは空です" unableToDelete: "削除できません" @@ -438,6 +454,7 @@ totpDescription: "認証アプリを使ってワンタイムパスワードを moderator: "モデレーター" moderation: "モデレーション" moderationNote: "モデレーションノート" +moderationNoteDescription: "モデレーター間でだけ共有されるメモを記入することができます。" addModerationNote: "モデレーションノートを追加する" moderationLogs: "モデログ" nUsersMentioned: "{n}人が投稿" @@ -476,7 +493,8 @@ attachAsFileQuestion: "クリップボードのテキストが長いです。テ noMessagesYet: "まだチャットはありません" newMessageExists: "新しいメッセージがあります" onlyOneFileCanBeAttached: "メッセージに添付できるファイルはひとつです" -signinRequired: "続行する前に、サインアップまたはサインインが必要です" +signinRequired: "続行する前に、登録またはログインが必要です" +signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があります" invitations: "招待" invitationCode: "招待コード" checking: "確認しています" @@ -498,7 +516,10 @@ uiLanguage: "UIの表示言語" aboutX: "{x}について" emojiStyle: "絵文字のスタイル" native: "ネイティブ" -disableDrawer: "メニューをドロワーで表示しない" +menuStyle: "メニューのスタイル" +style: "スタイル" +drawer: "ドロワー" +popup: "ポップアップ" showNoteActionsOnlyHover: "ノートのアクションをホバー時のみ表示する" showReactionsCount: "ノートのリアクション数を表示する" noHistory: "履歴はありません" @@ -581,6 +602,8 @@ ascendingOrder: "昇順" descendingOrder: "降順" scratchpad: "スクラッチパッド" scratchpadDescription: "スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。" +uiInspector: "UIインスペクター" +uiInspectorDescription: "メモリ上に存在しているUIコンポーネントのインスタンスの一覧を見ることができます。UIコンポーネントはUi:C:系関数により生成されます。" output: "出力" script: "スクリプト" disablePagesScript: "Pagesのスクリプトを無効にする" @@ -692,15 +715,12 @@ abuseReports: "通報" reportAbuse: "通報" reportAbuseRenote: "リノートを通報" reportAbuseOf: "{name}を通報する" -fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。" +fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートやページなどがある場合はそのURLも記入してください。" abuseReported: "内容が送信されました。ご報告ありがとうございました。" reporter: "通報者" reporteeOrigin: "通報先" reporterOrigin: "通報元" -forwardReport: "リモートサーバーに通報を転送する" -forwardReportIsAnonymous: "リモートサーバーからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。" send: "送信" -abuseMarkAsResolved: "対応済みにする" openInNewTab: "新しいタブで開く" openInSideView: "サイドビューで開く" defaultNavigationBehaviour: "デフォルトのナビゲーション" @@ -765,7 +785,7 @@ left: "左" center: "中央" wide: "広い" narrow: "狭い" -reloadToApplySetting: "設定はページリロード後に反映されます。今すぐリロードしますか?" +reloadToApplySetting: "設定はページリロード後に反映されます。" needReloadToApply: "反映には再起動が必要です。" showTitlebar: "タイトルバーを表示する" clearCache: "キャッシュをクリア" @@ -902,6 +922,7 @@ followersVisibility: "フォロワーの公開範囲" continueThread: "さらにスレッドを見る" deleteAccountConfirm: "アカウントが削除されます。よろしいですか?" incorrectPassword: "パスワードが間違っています。" +incorrectTotp: "ワンタイムパスワードが間違っているか、期限切れになっています。" voteConfirm: "「{choice}」に投票しますか?" hide: "隠す" useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示" @@ -1101,6 +1122,8 @@ preservedUsernames: "予約ユーザー名" preservedUsernamesDescription: "予約するユーザー名を改行で列挙します。ここで指定されたユーザー名はアカウント作成時に使えなくなりますが、管理者によるアカウント作成時はこの制限を受けません。また、既に存在するアカウントも影響を受けません。" createNoteFromTheFile: "このファイルからノートを作成" archive: "アーカイブ" +archived: "アーカイブ済み" +unarchive: "アーカイブ解除" channelArchiveConfirmTitle: "{name}をアーカイブしますか?" channelArchiveConfirmDescription: "アーカイブすると、チャンネル一覧や検索結果に表示されなくなり、新たな書き込みもできなくなります。" thisChannelArchived: "このチャンネルはアーカイブされています。" @@ -1111,6 +1134,9 @@ preventAiLearning: "生成AIによる学習を拒否" preventAiLearningDescription: "外部の文章生成AIや画像生成AIに対して、投稿したノートや画像などのコンテンツを学習の対象にしないように要求します。これはnoaiフラグをHTMLレスポンスに含めることによって実現されますが、この要求に従うかはそのAI次第であるため、学習を完全に防止するものではありません。" options: "オプション" specifyUser: "ユーザー指定" +lookupConfirm: "照会しますか?" +openTagPageConfirm: "ハッシュタグのページを開きますか?" +specifyHost: "ホスト指定" failedToPreviewUrl: "プレビューできません" update: "更新" rolesThatCanBeUsedThisEmojiAsReaction: "リアクションとして使えるロール" @@ -1242,6 +1268,34 @@ keepOriginalFilenameDescription: "この設定をオフにすると、アップ noDescription: "説明文はありません" alwaysConfirmFollow: "フォローの際常に確認する" inquiry: "お問い合わせ" +tryAgain: "もう一度お試しください。" +confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示するとき確認する" +sensitiveMediaRevealConfirm: "センシティブなメディアです。表示しますか?" +createdLists: "作成したリスト" +createdAntennas: "作成したアンテナ" +fromX: "{x}から" +genEmbedCode: "埋め込みコードを生成" +noteOfThisUser: "このユーザーのノート一覧" +clipNoteLimitExceeded: "これ以上このクリップにノートを追加できません。" +performance: "パフォーマンス" +modified: "変更あり" +discard: "破棄" +thereAreNChanges: "{n}件の変更があります" +signinWithPasskey: "パスキーでログイン" +unknownWebAuthnKey: "登録されていないパスキーです。" +passkeyVerificationFailed: "パスキーの検証に失敗しました。" +passkeyVerificationSucceededButPasswordlessLoginDisabled: "パスキーの検証に成功しましたが、パスワードレスログインが無効になっています。" +messageToFollower: "フォロワーへのメッセージ" +target: "対象" +testCaptchaWarning: "CAPTCHAのテストを目的とした機能です。本番環境で使用しないでください。" + +_abuseUserReport: + forward: "転送" + forwardDescription: "匿名のシステムアカウントとして、リモートサーバーに通報を転送します。" + resolve: "解決" + accept: "是認" + reject: "否認" + resolveTutorial: "内容が正当である通報に対応した場合は「是認」を選択し、肯定的にケースが解決されたことをマークします。\n内容が正当でない通報の場合は「否認」を選択し、否定的にケースが解決されたことをマークします。" _delivery: status: "配信状態" @@ -1384,8 +1438,10 @@ _serverSettings: fanoutTimelineDescription: "有効にすると、各種タイムラインを取得する際のパフォーマンスが大幅に向上し、データベースへの負荷を軽減することが可能です。ただし、Redisのメモリ使用量は増加します。サーバーのメモリ容量が少ない場合、または動作が不安定な場合は無効にすることができます。" fanoutTimelineDbFallback: "データベースへのフォールバック" fanoutTimelineDbFallbackDescription: "有効にすると、タイムラインがキャッシュされていない場合にDBへ追加で問い合わせを行うフォールバック処理を行います。無効にすると、フォールバック処理を行わないことでさらにサーバーの負荷を軽減することができますが、タイムラインが取得できる範囲に制限が生じます。" + reactionsBufferingDescription: "有効にすると、リアクション作成時のパフォーマンスが大幅に向上し、データベースへの負荷を軽減することが可能です。ただし、Redisのメモリ使用量は増加します。" inquiryUrl: "問い合わせ先URL" inquiryUrlDescription: "サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定します。" + thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。" _accountMigration: moveFrom: "別のアカウントからこのアカウントに移行" @@ -1705,6 +1761,7 @@ _role: canManageAvatarDecorations: "アバターデコレーションの管理" driveCapacity: "ドライブ容量" alwaysMarkNsfw: "ファイルにNSFWを常に付与" + canUpdateBioMedia: "アイコンとバナーの更新を許可" pinMax: "ノートのピン留めの最大数" antennaMax: "アンテナの作成可能数" wordMuteMax: "ワードミュートの最大文字数" @@ -1719,6 +1776,11 @@ _role: canSearchNotes: "ノート検索の利用" canUseTranslator: "翻訳機能の利用" avatarDecorationLimit: "アイコンデコレーションの最大取付個数" + canImportAntennas: "アンテナのインポートを許可" + canImportBlocking: "ブロックのインポートを許可" + canImportFollowing: "フォローのインポートを許可" + canImportMuting: "ミュートのインポートを許可" + canImportUserLists: "リストのインポートを許可" _condition: roleAssignedTo: "マニュアルロールにアサイン済み" isLocal: "ローカルユーザー" @@ -1958,7 +2020,6 @@ _theme: buttonBg: "ボタンの背景" buttonHoverBg: "ボタンの背景 (ホバー)" inputBorder: "入力ボックスの縁取り" - listItemHoverBg: "リスト項目の背景 (ホバー)" driveFolderBg: "ドライブフォルダーの背景" wallpaperOverlay: "壁紙のオーバーレイ" badge: "バッジ" @@ -1971,8 +2032,6 @@ _sfx: note: "ノート" noteMy: "ノート(自分)" notification: "通知" - antenna: "アンテナ受信" - channel: "チャンネル通知" reaction: "リアクション選択時" _soundSettings: @@ -1982,6 +2041,7 @@ _soundSettings: driveFileTypeWarnDescription: "音声ファイルを選択してください" driveFileDurationWarn: "音声が長すぎます" driveFileDurationWarnDescription: "長い音声を使用するとMisskeyの使用に支障をきたす可能性があります。それでも続行しますか?" + driveFileError: "音声が読み込めませんでした。設定を変更してください" _ago: future: "未来" @@ -2252,6 +2312,9 @@ _profile: changeBanner: "バナー画像を変更" verifiedLinkDescription: "内容にURLを設定すると、リンク先のWebサイトに自分のプロフィールへのリンクが含まれている場合に所有者確認済みアイコンを表示させることができます。" avatarDecorationMax: "最大{max}つまでデコレーションを付けられます。" + followedMessage: "フォローされた時のメッセージ" + followedMessageDescription: "フォローされた時に相手に表示する短いメッセージを設定できます。" + followedMessageDescriptionForLockedAccount: "フォローを承認制にしている場合、フォローリクエストを許可した時に表示されます。" _exportOrImport: allNotes: "全てのノート" @@ -2350,6 +2413,7 @@ _pages: eyeCatchingImageSet: "アイキャッチ画像を設定" eyeCatchingImageRemove: "アイキャッチ画像を削除" chooseBlock: "ブロックを追加" + enterSectionTitle: "セクションタイトルを入力" selectType: "種類を選択" contentBlocks: "コンテンツ" inputBlocks: "入力" @@ -2398,6 +2462,8 @@ _notification: renotedBySomeUsers: "{n}人がリノートしました" followedBySomeUsers: "{n}人にフォローされました" flushNotification: "通知の履歴をリセットする" + exportOfXCompleted: "{x}のエクスポートが完了しました" + login: "ログインがありました" _types: all: "すべて" @@ -2413,6 +2479,9 @@ _notification: followRequestAccepted: "フォローが受理された" roleAssigned: "ロールが付与された" achievementEarned: "実績の獲得" + exportCompleted: "エクスポートが完了した" + login: "ログイン" + test: "通知のテスト" app: "連携アプリからの通知" _actions: @@ -2471,7 +2540,7 @@ _webhookSettings: modifyWebhook: "Webhookを編集" name: "名前" secret: "シークレット" - events: "Webhookを実行するタイミング" + trigger: "トリガー" active: "有効" _events: follow: "フォローしたとき" @@ -2484,7 +2553,9 @@ _webhookSettings: _systemEvents: abuseReport: "ユーザーから通報があったとき" abuseReportResolved: "ユーザーからの通報を処理したとき" + userCreated: "ユーザーが作成されたとき" deleteConfirm: "Webhookを削除しますか?" + testRemarks: "スイッチの右にあるボタンをクリックするとダミーのデータを使用したテスト用Webhookを送信できます。" _abuseReport: _notificationRecipient: @@ -2530,6 +2601,8 @@ _moderationLogTypes: markSensitiveDriveFile: "ファイルをセンシティブ付与" unmarkSensitiveDriveFile: "ファイルをセンシティブ解除" resolveAbuseReport: "通報を解決" + forwardAbuseReport: "通報を転送" + updateAbuseReportNote: "通報のモデレーションノート更新" createInvitation: "招待コードを作成" createAd: "広告を作成" deleteAd: "広告を削除" @@ -2545,6 +2618,10 @@ _moderationLogTypes: createAbuseReportNotificationRecipient: "通報の通知先を作成" updateAbuseReportNotificationRecipient: "通報の通知先を更新" deleteAbuseReportNotificationRecipient: "通報の通知先を削除" + deleteAccount: "アカウントを削除" + deletePage: "ページを削除" + deleteFlash: "Playを削除" + deleteGalleryPost: "ギャラリーの投稿を削除" _fileViewer: title: "ファイルの詳細" @@ -2684,3 +2761,24 @@ _mediaControls: pip: "ピクチャインピクチャ" playbackRate: "再生速度" loop: "ループ再生" + +_contextMenu: + title: "コンテキストメニュー" + app: "アプリケーション" + appWithShift: "Shiftキーでアプリケーション" + native: "ブラウザのUI" + +_embedCodeGen: + title: "埋め込みコードをカスタマイズ" + header: "ヘッダーを表示" + autoload: "自動で続きを読み込む(非推奨)" + maxHeight: "高さの最大値" + maxHeightDescription: "0で最大値の設定が無効になります。ウィジェットが縦に伸び続けるのを防ぐために、何らかの値に指定してください。" + maxHeightWarn: "高さの最大値制限が無効(0)になっています。これが意図した変更ではない場合は、高さの最大値を何らかの値に設定してください。" + previewIsNotActual: "プレビュー画面で表示可能な範囲を超えたため、実際に埋め込んだ際とは表示が異なります。" + rounded: "角丸にする" + border: "外枠に枠線をつける" + applyToPreview: "プレビューに反映" + generateCode: "埋め込みコードを作成" + codeGenerated: "コードが生成されました" + codeGeneratedDescription: "生成されたコードをウェブサイトに貼り付けてご利用ください。" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 7a33968e9e..0a8b3828f2 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -60,6 +60,7 @@ copyFileId: "ファイルIDをコピー" copyFolderId: "フォルダーIDをコピー" copyProfileUrl: "プロフィールURLをコピー" searchUser: "ユーザーを探す" +searchThisUsersNotes: "ユーザーのノートを検索" reply: "返事" loadMore: "まだまだあるで!" showMore: "まだまだあるで!" @@ -108,11 +109,14 @@ enterEmoji: "絵文字を入れてや" renote: "リノート" unrenote: "リノートやめる" renoted: "リノートしたで。" +renotedToX: "{name}にリノートしたで" cantRenote: "この投稿はリノートできへんっぽい。" cantReRenote: "リノート自体はリノートできへんで。" quote: "引用" inChannelRenote: "チャンネルの中でリノート" inChannelQuote: "チャンネル内引用" +renoteToChannel: "チャンネルにリノート" +renoteToOtherChannel: "他のチャンネルにリノート" pinnedNote: "ピン留めされとるノート" pinned: "ピン留めしとく" you: "あんた" @@ -151,6 +155,7 @@ editList: "リストいじる" selectChannel: "チャンネルを選ぶ" selectAntenna: "アンテナを選ぶ" editAntenna: "アンテナいじる" +createAntenna: "アンテナを作成" selectWidget: "ウィジェットを選ぶ" editWidgets: "ウィジェットをいじる" editWidgetsExit: "いじるのをやめる" @@ -177,6 +182,10 @@ addAccount: "アカウントを追加" reloadAccountsList: "アカウントリストの情報を更新" loginFailed: "ログインに失敗してもうた…" showOnRemote: "リモートで見る" +continueOnRemote: "リモートで続行" +chooseServerOnMisskeyHub: "Misskey Hubからサーバーを選択" +specifyServerHost: "サーバーのドメインを直接指定" +inputHostName: "ドメインを入力せえや" general: "全般" wallpaper: "壁紙" setWallpaper: "壁紙を設定" @@ -187,6 +196,7 @@ followConfirm: "{name}をフォローしてええか?" proxyAccount: "プロキシアカウント" proxyAccountDescription: "プロキシアカウントは、代わりにフォローしてくれるアカウントや。例えば、551に豚まんが無いときやったり、ユーザーがリモートユーザーをアカウントに入れたとき、リストに入れられたユーザーが誰からもフォローされてないと寂しいやん。寂しいし、アクティビティも配達されへんから、プロキシアカウントがフォローしてくれるで。ええやつやん…" host: "ホスト" +selectSelf: "自分を選択" selectUser: "ユーザーを選ぶ" recipient: "宛先" annotation: "注釈" @@ -202,6 +212,7 @@ perDay: "1日ごと" stopActivityDelivery: "アクティビティの配送をやめる" blockThisInstance: "このサーバーをブロックすんで" silenceThisInstance: "サーバーサイレンスすんで?" +mediaSilenceThisInstance: "サーバーをメディアサイレンス" operations: "操作" software: "ソフトウェア" version: "バージョン" @@ -223,6 +234,8 @@ blockedInstances: "ブロックしたサーバー" blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定してな。ブロックされてもうたサーバーとはもう金輪際やり取りできひんくなるで。" silencedInstances: "サーバーサイレンスされてんねん" silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定すんで。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなんねん。ブロックしたインスタンスには影響せーへんで。" +mediaSilencedInstances: "メディアサイレンスしたサーバー" +mediaSilencedInstancesDescription: "メディアサイレンスしたいサーバーのホストを改行で区切って設定するで。メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われてな、カスタム絵文字が使えへんようになるで。ブロックしたインスタンスには影響せえへんで。" muteAndBlock: "ミュートとブロック" mutedUsers: "ミュートしとるユーザー" blockedUsers: "ブロックしとるユーザー" @@ -313,6 +326,7 @@ selectFile: "ファイル選んでや" selectFiles: "ファイル選んでや" selectFolder: "フォルダ選んでや" selectFolders: "フォルダ選んでや" +fileNotSelected: "ファイルが選択されてへんで" renameFile: "ファイル名をいらう" folderName: "フォルダー名" createFolder: "フォルダー作る" @@ -468,10 +482,12 @@ retype: "もっかい入力" noteOf: "{user}はんのノート" quoteAttached: "引用付いとるで" quoteQuestion: "引用として添付してもええか?" +attachAsFileQuestion: "クリップボードのテキストが長すぎるからテキストファイルとして添付してもええか?" noMessagesYet: "まだチャットはあらへんで" newMessageExists: "新しいメッセージがきたで" onlyOneFileCanBeAttached: "ごめんな、メッセージに添付できるファイルはひとつだけなんよ。" signinRequired: "ログインしてくれへん?" +signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があるで" invitations: "来てや" invitationCode: "招待コード" checking: "確認しとるで" @@ -493,7 +509,6 @@ uiLanguage: "UIの表示言語" aboutX: "{x}について" emojiStyle: "絵文字のスタイル" native: "ネイティブ" -disableDrawer: "メニューをドロワーで表示せえへん" showNoteActionsOnlyHover: "ノートの操作部をホバー時のみ表示するで" showReactionsCount: "ノートのリアクション数を表示する" noHistory: "履歴はないわ。" @@ -692,10 +707,7 @@ abuseReported: "無事内容が送信されたみたいやで。おおきに〜 reporter: "通報者" reporteeOrigin: "通報先" reporterOrigin: "通報元" -forwardReport: "リモートサーバーに通報を転送するで" -forwardReportIsAnonymous: "リモートサーバーからはあんたの情報は見えんなって、匿名のシステムアカウントとして表示されるで。" send: "送信" -abuseMarkAsResolved: "対応したで" openInNewTab: "新しいタブで開く" openInSideView: "サイドビューで開く" defaultNavigationBehaviour: "デフォルトのナビゲーション" @@ -832,6 +844,7 @@ administration: "管理" accounts: "アカウント" switch: "切り替え" noMaintainerInformationWarning: "管理者情報が設定されてへんで" +noInquiryUrlWarning: "問い合わせ先URLが設定されてへんで。" noBotProtectionWarning: "Botプロテクションが設定されてへんで。" configure: "設定する" postToGallery: "ギャラリーへ投稿" @@ -1021,6 +1034,7 @@ thisPostMayBeAnnoyingHome: "ホームに投稿" thisPostMayBeAnnoyingCancel: "やめとく" thisPostMayBeAnnoyingIgnore: "このまま投稿" collapseRenotes: "見たことあるリノートは飛ばして表示するで" +collapseRenotesDescription: "リアクションやリノートをしたことがあるノートをたたんで表示するで。" internalServerError: "サーバー内部エラー" internalServerErrorDescription: "サーバーでなんか変なこと起こっとるわ。" copyErrorInfo: "エラー情報をコピるで" @@ -1094,6 +1108,8 @@ preservedUsernames: "予約ユーザー名" preservedUsernamesDescription: "予約しとくユーザー名を行ごとに挙げるで。ここで指定されたユーザー名はアカウント作るときに使えへんくなるけど、管理者は例外や。あと、もうあるアカウントも例外やな。" createNoteFromTheFile: "このファイル使うてノート作るで" archive: "アーカイブ" +archived: "アーカイブ済み" +unarchive: "アーカイブ解除" channelArchiveConfirmTitle: "{name}をアーカイブしてええか?" channelArchiveConfirmDescription: "アーカイブしたら、チャンネル一覧とか検索結果からなくなるし、新しく書き込みもできへんなるで。" thisChannelArchived: "このチャンネル、アーカイブされとるで。" @@ -1104,6 +1120,9 @@ preventAiLearning: "生成AIの学習に使わんといて" preventAiLearningDescription: "他の文章生成AIとか画像生成AIに、投稿したノートとか画像なんかを勝手に使わんように頼むで。具体的にはnoaiフラグをHTMLレスポンスに含めるんやけど、これ聞いてくれるんはAIの気分次第やから、使われる可能性もちょっとはあるな。" options: "オプション" specifyUser: "ユーザー指定" +lookupConfirm: "照会するけどええか?" +openTagPageConfirm: "ハッシュタグのページを開くんか?" +specifyHost: "ホスト指定" failedToPreviewUrl: "プレビューできへん" update: "更新" rolesThatCanBeUsedThisEmojiAsReaction: "ツッコミとして使えるロール" @@ -1235,10 +1254,20 @@ keepOriginalFilenameDescription: "この設定をオフにすると、アップ noDescription: "説明文はあらへんで" alwaysConfirmFollow: "フォローの際常に確認する" inquiry: "問い合わせ" +tryAgain: "もう一度試しいや。" +confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示するとき確認する" +sensitiveMediaRevealConfirm: "センシティブなメディアやで。表示するんか?" +createdLists: "作成したリスト" +createdAntennas: "作成したアンテナ" _delivery: + status: "配信状態" stop: "配信せぇへん" + resume: "配信再開" _type: none: "配信しとる" + manuallySuspended: "手動停止中" + goneSuspended: "サーバー削除のため停止中" + autoSuspendedForNotResponding: "サーバー応答せえへんから停止中" _bubbleGame: howToPlay: "遊び方" hold: "ホールド" @@ -1364,6 +1393,8 @@ _serverSettings: fanoutTimelineDescription: "入れると、おのおのタイムラインを取得するときにめちゃめちゃ動きが良うなって、データベースが軽くなるわ。でも、Redisのメモリ使う量が増えるから注意な。サーバーのメモリが足りんときとか、動きが変なときは切れるで。" fanoutTimelineDbFallback: "データベースにフォールバックする" fanoutTimelineDbFallbackDescription: "有効にしたら、タイムラインがキャッシュん中に入ってないときにDBにもっかい問い合わせるフォールバック処理ってのをやっとくで。切ったらフォールバック処理をやらんからサーバーはもっと軽くなんねんけど、タイムラインの取得範囲がちょっと減るで。" + inquiryUrl: "問い合わせ先URL" + inquiryUrlDescription: "サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定するで。" _accountMigration: moveFrom: "別のアカウントからこのアカウントに引っ越す" moveFromSub: "別のアカウントへエイリアスを作る" @@ -1680,6 +1711,7 @@ _role: canManageAvatarDecorations: "アバターを飾るモンの管理" driveCapacity: "ドライブ容量" alwaysMarkNsfw: "勝手にファイルにNSFWをくっつける" + canUpdateBioMedia: "アイコンとバナーの更新を許可" pinMax: "ノートピン留めできる数" antennaMax: "アンテナ作れる数" wordMuteMax: "ワードミュートの最大文字数" @@ -1911,7 +1943,6 @@ _theme: buttonBg: "ボタンの背景" buttonHoverBg: "ボタンの背景 (ホバー)" inputBorder: "入力ボックスの縁取り" - listItemHoverBg: "リスト項目の背景 (ホバー)" driveFolderBg: "ドライブフォルダーの背景" wallpaperOverlay: "壁紙のオーバーレイ" badge: "バッジ" @@ -1923,8 +1954,6 @@ _sfx: note: "ノート" noteMy: "ノート(自分)" notification: "通知" - antenna: "アンテナ受信" - channel: "チャンネル通知" reaction: "ツッコミ選んどるとき" _soundSettings: driveFile: "ドライブん中の音使う" @@ -1933,6 +1962,7 @@ _soundSettings: driveFileTypeWarnDescription: "音声ファイルを選びや" driveFileDurationWarn: "音が長すぎるわ" driveFileDurationWarnDescription: "長い音使うたらMisskey使うのに良うないかもしれへんで。それでもええか?" + driveFileError: "音声が読み込めへんかったで。設定を変更せえや" _ago: future: "未来" justNow: "ついさっき" @@ -2340,6 +2370,7 @@ _notification: followRequestAccepted: "フォローが受理されたで" roleAssigned: "ロールが付与された" achievementEarned: "実績の獲得" + login: "ログイン" app: "連携アプリからの通知や" _actions: followBack: "フォローバック" @@ -2349,6 +2380,7 @@ _deck: alwaysShowMainColumn: "いつもメインカラムを表示" columnAlign: "カラムの寄せ" addColumn: "カラムを追加" + newNoteNotificationSettings: "新着ノート通知の設定" configureColumn: "カラムの設定" swapLeft: "左に移動" swapRight: "右に移動" @@ -2387,9 +2419,10 @@ _drivecleaner: orderByCreatedAtAsc: "追加日の古い順" _webhookSettings: createWebhook: "Webhookをつくる" + modifyWebhook: "Webhookを編集" name: "名前" secret: "シークレット" - events: "Webhookを投げるタイミング" + trigger: "トリガー" active: "有効" _events: follow: "フォローしたとき~!" @@ -2399,6 +2432,26 @@ _webhookSettings: renote: "リノートされるとき~!" reaction: "ツッコまれたとき~!" mention: "メンションがあるとき~!" + _systemEvents: + abuseReport: "ユーザーから通報があったとき" + abuseReportResolved: "ユーザーからの通報を処理したとき" + userCreated: "ユーザーが作成されたとき" + deleteConfirm: "ほんまにWebhookをほかしてもええんか?" +_abuseReport: + _notificationRecipient: + createRecipient: "通報の通知先を追加" + modifyRecipient: "通報の通知先を編集" + recipientType: "通知先の種類" + _recipientType: + mail: "メール" + webhook: "Webhook" + _captions: + mail: "モデレーター権限を持つユーザーのメアドに通知を送るで(通報を受けた時のみ)" + webhook: "指定したSystemWebhookに通知を送るで(通報を受けた時と通報を解決した時にそれぞれ発信)" + keywords: "キーワード" + notifiedUser: "通知先ユーザー" + notifiedWebhook: "使用するWebhook" + deleteConfirm: "通知先を削除してもええか?" _moderationLogTypes: createRole: "ロールを追加すんで" deleteRole: "ロールほかす" @@ -2436,6 +2489,8 @@ _moderationLogTypes: deleteAvatarDecoration: "アイコンデコレーションを削除" unsetUserAvatar: "この子のアイコン元に戻す" unsetUserBanner: "この子のバナー元に戻す" + createSystemWebhook: "SystemWebhookを作成" + updateSystemWebhook: "SystemWebhookを更新" _fileViewer: title: "ファイルの詳しい情報" type: "ファイルの種類" diff --git a/locales/kab-KAB.yml b/locales/kab-KAB.yml index 22e24d3baa..d4aa36fa70 100644 --- a/locales/kab-KAB.yml +++ b/locales/kab-KAB.yml @@ -104,3 +104,7 @@ _deck: _columns: notifications: "Ilɣuyen" list: "Tibdarin" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Imayl" diff --git a/locales/kn-IN.yml b/locales/kn-IN.yml index b3ad46f2b1..222599572a 100644 --- a/locales/kn-IN.yml +++ b/locales/kn-IN.yml @@ -77,6 +77,8 @@ _profile: username: "ಬಳಕೆಹೆಸರು" _notification: youWereFollowed: "ಹಿಂಬಾಲಿಸಿದರು" + _types: + login: "ಪ್ರವೇಶ" _actions: reply: "ಉತ್ತರಿಸು" _deck: diff --git a/locales/ko-GS.yml b/locales/ko-GS.yml index 9466aff01f..6c667b48da 100644 --- a/locales/ko-GS.yml +++ b/locales/ko-GS.yml @@ -476,7 +476,6 @@ uiLanguage: "UI 표시 언어" aboutX: "{x}에 대해서" emojiStyle: "이모지 모양" native: "기본" -disableDrawer: "드로어 메뉴 쓰지 않기" showNoteActionsOnlyHover: "마우스 올맀을 때만 노트 액션 버턴 보이기" noHistory: "기록이 없십니다" signinHistory: "로그인 기록" @@ -583,6 +582,9 @@ describeFile: "캡션 옇기" enterFileDescription: "캡션 서기" author: "맨던 사람" manage: "간리" +large: "커게" +medium: "엔갆게" +small: "쪼맪게" emailServer: "전자우펜 서버" email: "전자우펜" emailAddress: "전자우펜 주소" @@ -599,7 +601,6 @@ reportAbuseOf: "{name}님얼 신고하기" reporter: "신고한 사람" reporteeOrigin: "신고덴 사람" reporterOrigin: "신고한 곳" -forwardReport: "웬겍 서버에 신고 보내기" waitingFor: "{x}(얼)럴 지달리고 잇십니다" random: "무작이" system: "시스템" @@ -613,12 +614,14 @@ followersCount: "팔로워 수" noteFavoritesCount: "질겨찾기한 노트 수" clips: "클립 맨걸기" clearCache: "캐시 비우기" +nUsers: "{n} 사용자" typingUsers: "{users} 님이 서고 잇어예" unlikeConfirm: "좋네예럴 무룹니꺼?" info: "정보" selectAccount: "계정 개리기" user: "사용자" administration: "간리" +middle: "엔갆게" translatedFrom: "{x}서 번옉" on: "킴" off: "껌" @@ -633,6 +636,7 @@ oneMonth: "한 달" file: "파일" typeToConfirm: "게속할라먼 {x}럴 누질라 주이소" pleaseSelect: "개리 주이소" +remoteOnly: "웬겍만" tools: "도구" like: "좋네예!" unlike: "좋네예 무루기" @@ -643,7 +647,10 @@ role: "옉할" noRole: "옉할이 어ᇝ십니다" thisPostMayBeAnnoyingCancel: "아이예" likeOnly: "좋네예마" +hiddenTags: "수ᇚ훈 해시태그" myClips: "내 클립" +preservedUsernames: "예약 사용자 이럼" +specifyUser: "사용자 지정" icon: "아바타" replies: "답하기" renotes: "리노트" @@ -709,6 +716,16 @@ _achievements: description: "0분 0초에 노트를 섰어예" _tutorialCompleted: description: "길라잡이럴 껕냇십니다" +_role: + displayOrder: "보기 순서" + _priority: + middle: "엔갆게" + _options: + canHideAds: "강고 수ᇚ후기" + _condition: + isRemote: "웬겍 사용자" + isCat: "갱이 사용자" + isBot: "자동 사용자" _gallery: my: "내 걸" liked: "좋네예한 걸" @@ -794,6 +811,7 @@ _notification: mention: "멘션" quote: "따오기" reaction: "반엉" + login: "로그인" _actions: reply: "답하기" _deck: @@ -805,6 +823,10 @@ _deck: mentions: "받언 멘션" _webhookSettings: name: "이럼" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "전자우펜" _moderationLogTypes: suspend: "얼우기" deleteNote: "노트 뭉캐기" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 294a5a1520..973140dca2 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -8,6 +8,9 @@ search: "검색" notifications: "알림" username: "유저명" password: "비밀번호" +initialPasswordForSetup: "초기 설정용 비밀번호" +initialPasswordIsIncorrect: "초기 설정용 비밀번호가 올바르지 않습니다." +initialPasswordForSetupDescription: "Misskey를 직접 설치하는 경우, 설정 파일에 입력해둔 비밀번호를 사용하세요.\nMisskey 설치를 도와주는 호스팅 서비스 등을 사용하는 경우, 서비스 제공자로부터 받은 비밀번호를 사용하세요.\n비밀번호를 따로 설정하지 않은 경우, 아무것도 입력하지 않아도 됩니다." forgotPassword: "비밀번호 재설정" fetchingAsApObject: "연합에서 찾아보는 중" ok: "확인" @@ -53,13 +56,14 @@ addToList: "리스트에 추가" addToAntenna: "안테나에 추가" sendMessage: "메시지 보내기" copyRSS: "RSS 복사" -copyUsername: "사용자 이름 복사" -copyUserId: "사용자 ID 복사" +copyUsername: "유저명 복사" +copyUserId: "유저 ID 복사" copyNoteId: "노트 ID 복사" copyFileId: "파일 ID 복사" copyFolderId: "폴더 ID 복사" copyProfileUrl: "프로필 URL 복사" searchUser: "사용자 검색" +searchThisUsersNotes: "사용자의 노트 검색" reply: "답글" loadMore: "더 보기" showMore: "더 보기" @@ -108,22 +112,25 @@ enterEmoji: "이모지 입력" renote: "리노트" unrenote: "리노트 취소" renoted: "리노트했습니다" +renotedToX: "{name}명이 리노트했습니다." cantRenote: "이 게시물은 리노트 할 수 없습니다." -cantReRenote: "리노트를 리노트할 수 없습니다." +cantReRenote: "리노트를 리노트 할 수 없습니다." quote: "인용" inChannelRenote: "채널 내 리노트" inChannelQuote: "채널 내 인용" +renoteToChannel: "채널에 리노트" +renoteToOtherChannel: "다른 채널에 리노트" pinnedNote: "고정된 노트" pinned: "고정하기" you: "나" clickToShow: "클릭하여 보기" sensitive: "열람 주의" add: "추가" -reaction: "반응" -reactions: "반응" +reaction: "리액션" +reactions: "리액션" emojiPicker: "이모지 선택기" -pinnedEmojisForReactionSettingDescription: "리액션을 할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다" -pinnedEmojisSettingDescription: "이모지를 입력할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다" +pinnedEmojisForReactionSettingDescription: "리액션을 할 때 이모지 선택기 상단에 표시할 이모지를 설정할 수 있습니다." +pinnedEmojisSettingDescription: "이모지를 입력할 때 이모지 선택기 상단에 표시할 이모지를 설정할 수 있습니다." emojiPickerDisplay: "선택기 표시" overwriteFromPinnedEmojisForReaction: "리액션 설정을 덮어쓰기" overwriteFromPinnedEmojis: "일반 설정을 덮어쓰기" @@ -136,7 +143,7 @@ unmarkAsSensitive: "열람주의 해제" enterFileName: "파일명을 입력" mute: "뮤트" unmute: "뮤트 해제" -renoteMute: "리노트 뮤트하기" +renoteMute: "리노트 뮤트" renoteUnmute: "리노트 뮤트 해제" block: "차단" unblock: "차단 해제" @@ -151,6 +158,7 @@ editList: "리스트 편집" selectChannel: "채널 선택" selectAntenna: "안테나 선택" editAntenna: "안테나 편집" +createAntenna: "안테나 만들기" selectWidget: "위젯 선택" editWidgets: "위젯 편집" editWidgetsExit: "편집 종료" @@ -174,12 +182,16 @@ flagShowTimelineReplies: "타임라인에 노트의 답글을 표시하기" flagShowTimelineRepliesDescription: "이 설정을 활성화하면 타임라인에 다른 유저 간의 답글을 표시합니다." autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락" addAccount: "계정 추가" -reloadAccountsList: "계정 리스트 정보 갱신" +reloadAccountsList: "계정 목록 새로고침" loginFailed: "로그인에 실패했습니다" showOnRemote: "리모트에서 보기" +continueOnRemote: "리모트에서 계속" +chooseServerOnMisskeyHub: "Misskey Hub에서 서버 찾아보기" +specifyServerHost: "서버 도메인 직접 지정" +inputHostName: "도메인을 입력하세요" general: "일반" wallpaper: "배경" -setWallpaper: "배경화면 설정" +setWallpaper: "배경 설정" removeWallpaper: "배경 제거" searchWith: "검색: {q}" youHaveNoLists: "리스트가 없습니다" @@ -187,7 +199,8 @@ followConfirm: "{name}님을 팔로우 하시겠습니까?" proxyAccount: "프록시 계정" proxyAccountDescription: "프록시 계정은 특정 조건 하에서 유저의 리모트 팔로우를 대행하는 계정입니다. 예를 들면, 유저가 리모트 유저를 리스트에 넣었을 때, 리스트에 들어간 유저를 아무도 팔로우한 적이 없다면 액티비티가 서버로 배달되지 않기 때문에, 대신 프록시 계정이 해당 유저를 팔로우하도록 합니다." host: "호스트" -selectUser: "사용자 선택" +selectSelf: "본인을 선택" +selectUser: "유저 선택" recipient: "수신인" annotation: "내용에 대한 주석" federation: "연합" @@ -202,6 +215,7 @@ perDay: "1일마다" stopActivityDelivery: "액티비티 보내지 않기" blockThisInstance: "이 서버를 차단" silenceThisInstance: "서버를 사일런스" +mediaSilenceThisInstance: "서버의 미디어를 사일런스" operations: "작업" software: "소프트웨어" version: "버전" @@ -223,6 +237,10 @@ blockedInstances: "차단된 서버" blockedInstancesDescription: "차단하려는 서버의 호스트 이름을 줄바꿈으로 구분하여 설정합니다. 차단된 인스턴스는 이 인스턴스와 통신할 수 없게 됩니다." silencedInstances: "사일런스한 서버" silencedInstancesDescription: "사일런스하려는 서버의 호스트명을 한 줄에 하나씩 입력합니다. 사일런스된 서버에 소속된 유저는 모두 '사일런스'된 상태로 취급되며, 이 서버로부터의 팔로우가 프로필 설정과 무관하게 승인제로 변경되고, 팔로워가 아닌 로컬 유저에게는 멘션할 수 없게 됩니다. 정지된 서버에는 적용되지 않습니다." +mediaSilencedInstances: "미디어를 사일런스한 서버" +mediaSilencedInstancesDescription: "미디어를 사일런스 하려는 서버의 호스트를 한 줄에 하나씩 입력합니다. 미디어가 사일런스된 서버의 유저가 업로드한 파일은 모두 민감한 미디어로 처리되며, 커스텀 이모지를 사용할 수 없게 됩니다. 또한, 차단한 인스턴스에는 적용되지 않습니다." +federationAllowedHosts: "연합을 허가하는 서버" +federationAllowedHostsDescription: "연합을 허가하는 서버의 호스트를 엔터로 구분해서 설정합니다." muteAndBlock: "뮤트 및 차단" mutedUsers: "뮤트한 유저" blockedUsers: "차단한 유저" @@ -230,7 +248,7 @@ noUsers: "아무도 없습니다" editProfile: "프로필 수정" noteDeleteConfirm: "이 노트를 삭제하시겠습니까?" pinLimitExceeded: "더 이상 고정할 수 없습니다." -intro: "Misskey의 설치를 완료했습니다! 관리자 계정을 만들어 주세요." +intro: "Misskey의 설치가 완료되었습니다! 관리자 계정을 생성해주세요." done: "완료" processing: "처리중" preview: "미리보기" @@ -247,7 +265,7 @@ publishing: "배포 중" notResponding: "응답 없음" instanceFollowing: "서버의 팔로잉" instanceFollowers: "서버의 팔로워" -instanceUsers: "서버의 유저" +instanceUsers: "서버의 사용자" changePassword: "비밀번호 변경" security: "보안" retypedNotMatch: "입력이 일치하지 않습니다." @@ -263,12 +281,12 @@ lookup: "찾아보기" announcements: "공지사항" imageUrl: "이미지 URL" remove: "삭제" -removed: "삭제하였습니다" +removed: "삭제했습니다" removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?" deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?" resetAreYouSure: "초기화 하시겠습니까?" areYouSure: "계속 진행하시겠습니까?" -saved: "저장하였습니다" +saved: "저장했습니다" messaging: "대화" upload: "업로드" keepOriginalUploading: "원본 이미지를 유지" @@ -296,7 +314,7 @@ activity: "활동" images: "이미지" image: "이미지" birthday: "생일" -yearsOld: "만 {age} 세" +yearsOld: "{age}세" registeredDate: "등록일" location: "장소" theme: "테마" @@ -313,6 +331,7 @@ selectFile: "파일 선택" selectFiles: "파일 선택" selectFolder: "폴더 선택" selectFolders: "폴더 선택" +fileNotSelected: "파일을 선택하지 않았습니다" renameFile: "파일 이름 변경" folderName: "폴더 이름" createFolder: "폴더 만들기" @@ -320,6 +339,7 @@ renameFolder: "폴더 이름 바꾸기" deleteFolder: "폴더 삭제" folder: "폴더" addFile: "파일 추가" +showFile: "파일 표시하기" emptyDrive: "드라이브가 비어 있습니다" emptyFolder: "폴더가 비어 있습니다" unableToDelete: "삭제할 수 없습니다" @@ -365,12 +385,12 @@ registration: "등록" enableRegistration: "신규 회원가입을 활성화" invite: "초대" driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량" -driveCapacityPerRemoteAccount: "리모트 유저 한 명당 드라이브 용량" +driveCapacityPerRemoteAccount: "원격 사용자별 드라이브 용량" inMb: "메가바이트 단위" bannerUrl: "배너 이미지 URL" backgroundImageUrl: "배경 이미지 URL" basicInfo: "기본 정보" -pinnedUsers: "고정된 유저" +pinnedUsers: "고정한 사용자" pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다." pinnedPages: "고정한 페이지" pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다." @@ -434,16 +454,17 @@ totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력" moderator: "모더레이터" moderation: "조정" moderationNote: "조정 기록" +moderationNoteDescription: "모더레이터 역할을 가진 유저만 보이는 메모를 적을 수 있습니다." addModerationNote: "조정 기록 추가하기" moderationLogs: "모더레이션 로그" nUsersMentioned: "{n}명이 언급함" -securityKeyAndPasskey: "보안 키 또는 패스 키" +securityKeyAndPasskey: "보안 키 또는 패스키" securityKey: "보안 키" lastUsed: "마지막 사용" lastUsedAt: "마지막 사용: {t}" unregister: "등록 해제" passwordLessLogin: "비밀번호 없이 로그인" -passwordLessLoginDescription: "비밀번호를 사용하지 않고 보안 키 또는 패스 키 등으로만 로그인합니다." +passwordLessLoginDescription: "비밀번호 없이 보안 키 또는 패스키만 사용해서 로그인합니다." resetPassword: "비밀번호 재설정" newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다" reduceUiAnimation: "UI의 애니메이션을 줄이기" @@ -468,10 +489,12 @@ retype: "다시 입력" noteOf: "{user}의 노트" quoteAttached: "인용함" quoteQuestion: "인용해서 작성하시겠습니까?" +attachAsFileQuestion: "붙여넣으려는 글이 너무 깁니다. 텍스트 파일로 첨부하시겠습니까?" noMessagesYet: "아직 대화가 없습니다" newMessageExists: "새 메시지가 있습니다" onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다" signinRequired: "진행하기 전에 로그인을 해 주세요" +signinOrContinueOnRemote: "계속하려면 사용하는 서버로 이동하거나 이 서버에 로그인해야 합니다." invitations: "초대" invitationCode: "초대 코드" checking: "확인하는 중입니다" @@ -486,15 +509,18 @@ strongPassword: "강한 비밀번호" passwordMatched: "일치합니다" passwordNotMatched: "일치하지 않습니다" signinWith: "{x}로 로그인" -signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오." +signinFailed: "로그인할 수 없습니다. 사용자 이름과 비밀번호를 확인해 주십시오." or: "혹은" language: "언어" uiLanguage: "UI 표시 언어" aboutX: "{x}에 대하여" emojiStyle: "이모지 스타일" native: "기본" -disableDrawer: "드로어 메뉴를 사용하지 않기" -showNoteActionsOnlyHover: "노트 액션 버튼을 마우스를 올렸을 때에만 표시" +menuStyle: "메뉴 스타일" +style: "스타일" +drawer: "서랍" +popup: "팝업" +showNoteActionsOnlyHover: "마우스가 올라간 때에만 노트 동작 버튼을 표시하기" showReactionsCount: "노트의 반응 수를 표시하기" noHistory: "기록이 없습니다" signinHistory: "로그인 기록" @@ -559,7 +585,7 @@ popout: "새 창으로 열기" volume: "음량" masterVolume: "마스터 볼륨" notUseSound: "음소거 하기" -useSoundOnlyWhenActive: "Misskey가 활성화 되어져 있을 때만 소리 출력하기" +useSoundOnlyWhenActive: "Misskey를 활성화한 때에만 소리를 출력하기" details: "자세히" chooseEmoji: "이모지 선택" unableToProcess: "작업을 완료할 수 없습니다" @@ -576,6 +602,8 @@ ascendingOrder: "오름차순" descendingOrder: "내림차순" scratchpad: "스크래치 패드" scratchpadDescription: "스크래치 패드는 AiScript 의 테스트 환경을 제공합니다. Misskey 와 상호 작용하는 코드를 작성, 실행 및 결과를 확인할 수 있습니다." +uiInspector: "UI 인스펙터" +uiInspectorDescription: "메모리에 있는 UI 컴포넌트의 인스턴트 목록을 볼 수 있습니다. UI 컴포넌트는 Ui:C: 계열 함수로 만들어집니다." output: "출력" script: "스크립트" disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음" @@ -588,7 +616,7 @@ deleteAllFiles: "모든 파일 삭제" deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?" removeAllFollowing: "모든 팔로잉 해제" removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요." -userSuspended: "이 계정은 정지된 상태입니다." +userSuspended: "이 사용자는 정지되었습니다." userSilenced: "이 계정은 사일런스된 상태입니다." yourAccountSuspendedTitle: "계정이 정지되었습니다" yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오." @@ -692,10 +720,7 @@ abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다." reporter: "신고자" reporteeOrigin: "피신고자" reporterOrigin: "신고자" -forwardReport: "리모트 서버에도 신고 내용 보내기" -forwardReportIsAnonymous: "리모트 서버에서는 나의 정보를 볼 수 없으며, 익명의 시스템 계정으로 표시됩니다." send: "전송" -abuseMarkAsResolved: "해결됨으로 표시" openInNewTab: "새 탭에서 열기" openInSideView: "사이드뷰로 열기" defaultNavigationBehaviour: "기본 탐색 동작" @@ -752,7 +777,7 @@ experimentalFeatures: "실험실" experimental: "실험실" thisIsExperimentalFeature: "이 기능은 실험적인 기능입니다. 사양이 변경되거나 정상적으로 동작하지 않을 가능성이 있습니다." developer: "개발자" -makeExplorable: "\"발견하기\"에 내 계정 보이기" +makeExplorable: "계정을 쉽게 발견하도록 하기" makeExplorableDescription: "비활성화하면 \"발견하기\"에 나의 계정을 표시하지 않습니다." showGapBetweenNotesInTimeline: "타임라인의 노트 사이를 띄워서 표시" duplicate: "복제" @@ -798,7 +823,7 @@ emailNotification: "메일 알림" publish: "게시" inChannelSearch: "채널에서 검색" useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기" -typingUsers: "{users} 님이 입력하고 있어요.." +typingUsers: "{users}님이 입력 중" jumpToSpecifiedDate: "특정 날짜로 이동" showingPastTimeline: "과거의 타임라인을 표시하고 있어요" clear: "지우기" @@ -832,6 +857,7 @@ administration: "관리" accounts: "계정" switch: "전환" noMaintainerInformationWarning: "관리자 정보가 설정되어 있지 않습니다." +noInquiryUrlWarning: "문의처 주소를 설정하지 않았습니다." noBotProtectionWarning: "Bot 방어가 설정되어 있지 않습니다." configure: "설정하기" postToGallery: "갤러리에 업로드" @@ -896,6 +922,7 @@ followersVisibility: "팔로워의 공개 범위" continueThread: "글타래 더 보기" deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다. 계속하시겠습니까? " incorrectPassword: "비밀번호가 올바르지 않습니다." +incorrectTotp: "OTP 번호가 틀렸거나 유효기간이 만료되어 있을 수 있습니다." voteConfirm: "\"{choice}\"에 투표하시겠습니까?" hide: "숨기기" useDrawerReactionPickerForMobile: "모바일에서 드로어 메뉴로 표시" @@ -1021,6 +1048,7 @@ thisPostMayBeAnnoyingHome: "홈에 게시" thisPostMayBeAnnoyingCancel: "그만두기" thisPostMayBeAnnoyingIgnore: "이대로 게시" collapseRenotes: "이미 본 리노트를 간략화하기" +collapseRenotesDescription: "반응이나 리노트를 한 노트를 접어서 표시합니다." internalServerError: "내부 서버 오류" internalServerErrorDescription: "내부 서버에서 예기치 않은 오류가 발생했습니다." copyErrorInfo: "오류 정보 복사" @@ -1090,10 +1118,12 @@ serverRules: "서버 규칙" pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오." pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오." continue: "계속" -preservedUsernames: "예약된 사용자명" +preservedUsernames: "예약한 사용자 이름" preservedUsernamesDescription: "예약할 사용자명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 사용자명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다." createNoteFromTheFile: "이 파일로 노트를 작성" archive: "아카이브" +archived: "아카이브 됨" +unarchive: "보관 취소" channelArchiveConfirmTitle: "{name} 채널을 보존하시겠습니까?" channelArchiveConfirmDescription: "보존한 채널은 채널 목록과 검색 결과에 표시되지 않으며 새로운 노트도 작성할 수 없습니다." thisChannelArchived: "이 채널은 보존되었습니다." @@ -1104,6 +1134,9 @@ preventAiLearning: "기계학습(생성형 AI)으로의 사용을 거부" preventAiLearningDescription: "외부의 문장 생성 AI나 이미지 생성 AI에 대해 제출한 노트나 이미지 등의 콘텐츠를 학습의 대상으로 사용하지 않도록 요구합니다. 다만, 이 요구사항을 지킬 의무는 없기 때문에 학습을 완전히 방지하는 것은 아닙니다." options: "옵션" specifyUser: "사용자 지정" +lookupConfirm: "조회 할까요?" +openTagPageConfirm: "해시태그의 페이지를 열까요?" +specifyHost: "호스트 지정" failedToPreviewUrl: "미리 볼 수 없음" update: "업데이트" rolesThatCanBeUsedThisEmojiAsReaction: "이 이모지를 리액션으로 사용할 수 있는 역할" @@ -1230,10 +1263,46 @@ useTotp: "일회용 비밀번호 사용" useBackupCode: "백업 코드 사용" launchApp: "앱 실행" useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생" +keepOriginalFilename: "원본 파일 이름을 유지" +keepOriginalFilenameDescription: "이 설정을 끄면 업로드를 할 때 파일 이름이 자동으로 무작위 문자열로 바뀝니다." +noDescription: "설명문이 없습니다" +alwaysConfirmFollow: "팔로우일 때 항상 확인하기" +inquiry: "문의하기" +tryAgain: "다시 시도해 주세요." +confirmWhenRevealingSensitiveMedia: "민감한 미디어를 열 때 두 번 확인" +sensitiveMediaRevealConfirm: "민감한 미디어입니다. 표시할까요?" +createdLists: "만든 리스트" +createdAntennas: "만든 안테나" +fromX: "{x}부터" +genEmbedCode: "임베디드 코드 만들기" +noteOfThisUser: "이 유저의 노트 목록" +clipNoteLimitExceeded: "더 이상 이 클립에 노트를 추가 할 수 없습니다." +performance: "퍼포먼스" +modified: "변경 있음" +discard: "파기" +thereAreNChanges: "{n}건 변경이 있습니다." +signinWithPasskey: "패스키로 로그인" +unknownWebAuthnKey: "등록되지 않은 패스키입니다." +passkeyVerificationFailed: "패스키 검증을 실패했습니다." +passkeyVerificationSucceededButPasswordlessLoginDisabled: "패스키를 검증했으나, 비밀번호 없이 로그인하기가 꺼져 있습니다." +messageToFollower: "팔로워에 보낼 메시지" +target: "대상" +_abuseUserReport: + forward: "전달" + forwardDescription: "익명 시스템 계정을 사용하여 리모트 서버에 신고 내용을 전달할 수 있습니다." + resolve: "해결됨" + accept: "인용" + reject: "기각" + resolveTutorial: "적절한 신고 내용에 대응한 경우, \"인용\"을 선택하여 \"해결됨\"으로 기록합니다.\n적절하지 않은 신고를 받은 경우, \"기각\"을 선택하여 \"기각\"으로 기록합니다." _delivery: + status: "전송 상태" stop: "정지됨" + resume: "전송 다시 시작" _type: none: "배포 중" + manuallySuspended: "수동 정지 중" + goneSuspended: "서버 삭제를 이유로 정지 중" + autoSuspendedForNotResponding: "서버 응답 없음을 이유로 정지 중" _bubbleGame: howToPlay: "설명" hold: "홀드" @@ -1359,6 +1428,9 @@ _serverSettings: fanoutTimelineDescription: "활성화하면 각종 타임라인을 가져올 때의 성능을 대폭 향상하며, 데이터베이스의 부하를 줄일 수 있습니다. 단, Redis의 메모리 사용량이 증가합니다. 서버의 메모리 용량이 작거나, 서비스가 불안정해지는 경우 비활성화할 수 있습니다." fanoutTimelineDbFallback: "데이터베이스를 예비로 사용하기" fanoutTimelineDbFallbackDescription: "활성화하면 타임라인의 캐시되어 있지 않은 부분에 대해 DB에 질의하여 정보를 가져옵니다. 비활성화하면 이를 실행하지 않음으로써 서버의 부하를 줄일 수 있지만, 타임라인에서 가져올 수 있는 게시물 범위가 한정됩니다." + reactionsBufferingDescription: "활성화 한 경우, 리액션 작성 퍼포먼스가 대폭 향상되어 DB의 부하를 줄일 수 있으나, Redis의 메모리 사용량이 많아집니다." + inquiryUrl: "문의처 URL" + inquiryUrlDescription: "서버 운영자에게 보내는 문의 양식의 URL이나 운영자의 연락처 등이 적힌 웹 페이지의 URL을 설정합니다." _accountMigration: moveFrom: "다른 계정에서 이 계정으로 이사" moveFromSub: "다른 계정에 대한 별칭을 생성" @@ -1675,10 +1747,11 @@ _role: canManageAvatarDecorations: "아바타 꾸미기 관리" driveCapacity: "드라이브 용량" alwaysMarkNsfw: "파일을 항상 NSFW로 지정" + canUpdateBioMedia: "아바타 및 배너 이미지 변경 허용" pinMax: "고정할 수 있는 노트 수" antennaMax: "만들 수 있는 안테나 수" wordMuteMax: "단어 뮤트할 수 있는 문자 수" - webhookMax: "만들 수 있는 웹후크 수" + webhookMax: "만들 수 있는 Webhook 수" clipMax: "만들 수 있는 클립 수" noteEachClipsMax: "클립에 넣을 수 있는 노트 수" userListMax: "만들 수 있는 사용자 리스트 수" @@ -1689,10 +1762,20 @@ _role: canSearchNotes: "노트 검색 이용 가능 여부" canUseTranslator: "번역 기능의 사용" avatarDecorationLimit: "아바타 장식의 최대 붙임 개수" + canImportAntennas: "안테나 가져오기 허용" + canImportBlocking: "차단 목록 가져오기 허용" + canImportFollowing: "팔로우 가져오기 허용" + canImportMuting: "뮤트 목록 가져오기 허용" + canImportUserLists: "리스트 목록 가져오기 허용" _condition: roleAssignedTo: "수동 역할에 이미 할당됨" isLocal: "로컬 사용자" - isRemote: "리모트 사용자" + isRemote: "원격 사용자" + isCat: "고양이 사용자" + isBot: "봇 사용자" + isSuspended: "정지된 사용자" + isLocked: "잠금 계정 사용자" + isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 사용자" createdLessThan: "가입한 지 다음 일수 이내인 유저" createdMoreThan: "가입한 지 다음 일수 이상인 유저" followersLessThanOrEq: "팔로워 수가 다음 이하인 유저" @@ -1901,7 +1984,6 @@ _theme: buttonBg: "버튼 배경" buttonHoverBg: "버튼 배경 (호버)" inputBorder: "입력 필드 테두리" - listItemHoverBg: "리스트 항목 배경 (호버)" driveFolderBg: "드라이브 폴더 배경" wallpaperOverlay: "배경화면 오버레이" badge: "배지" @@ -1913,16 +1995,15 @@ _sfx: note: "새 노트" noteMy: "내 노트" notification: "알림" - antenna: "안테나 수신" - channel: "채널 알림" reaction: "리액션 선택" _soundSettings: driveFile: "드라이브에 있는 오디오를 사용" driveFileWarn: "드라이브에 있는 파일을 선택하세요." - driveFileTypeWarn: "이 파일은 지원되지 않습니다." + driveFileTypeWarn: "이 파이" driveFileTypeWarnDescription: "오디오 파일을 선택하세요." driveFileDurationWarn: "오디오가 너무 깁니다" driveFileDurationWarnDescription: "긴 오디오로 설정할 경우 미스키 사용에 지장이 갈 수도 있습니다. 그래도 괜찮습니까?" + driveFileError: "오디오를 불러올 수 없습니다. 설정을 바꿔주세요." _ago: future: "미래" justNow: "방금 전" @@ -1975,6 +2056,7 @@ _2fa: backupCodesDescription: "인증 앱을 사용할 수 없게 된 경우 아래 백업 코드를 사용하여 계정에 액세스 할 수 있습니다.이 코드들은 반드시 안전한 장소에 보관하십시오.각 코드는 한 번만 사용할 수 있습니다." backupCodeUsedWarning: "백업 코드가 사용되었습니다.인증 앱을 사용할 수 없게 된 경우, 조속히 인증 앱을 다시 설정해 주십시오." backupCodesExhaustedWarning: "백업 코드가 모두 사용되었습니다.인증 앱을 사용할 수 없는 경우 더 이상 계정에 액세스하는 것이 불가능합니다.인증 앱을 다시 등록해 주세요." + moreDetailedGuideHere: "여기에 자세한 설명이 있습니다" _permissions: "read:account": "계정의 정보를 봅니다" "write:account": "계정의 정보를 변경합니다" @@ -2163,7 +2245,7 @@ _postForm: c: "무엇을 생각하고 있나요?" d: "말하고 싶은 게 있나요?" e: "여기에 적어 주세요" - f: "글 쓰기를 기다려요…" + f: "작성해주시길 기다리고 있어요..." _profile: name: "이름" username: "사용자 이름" @@ -2178,6 +2260,9 @@ _profile: changeBanner: "배너 이미지 변경" verifiedLinkDescription: "내용에 자신의 프로필로 향하는 링크가 포함된 페이지의 URL을 삽입하면 소유자 인증 마크가 표시됩니다." avatarDecorationMax: "최대 {max}개까지 장식을 할 수 있습니다." + followedMessage: "팔로우 받았을 때 메시지" + followedMessageDescription: "팔로우 받았을 때 상대방에게 보여줄 단문 메시지를 설정할 수 있습니다." + followedMessageDescriptionForLockedAccount: "팔로우를 승인제로 한 경우, 팔로우 요청을 수락했을 때 보여줍니다." _exportOrImport: allNotes: "모든 노트" favoritedNotes: "즐겨찾기한 노트" @@ -2270,6 +2355,7 @@ _pages: eyeCatchingImageSet: "아이캐치 이미지를 설정" eyeCatchingImageRemove: "아이캐치 이미지를 삭제" chooseBlock: "블록 추가" + enterSectionTitle: "섹션 타이틀을 입력하기" selectType: "종류 선택" contentBlocks: "콘텐츠" inputBlocks: "입력" @@ -2315,6 +2401,8 @@ _notification: renotedBySomeUsers: "{n}명이 리노트했습니다" followedBySomeUsers: "{n}명에게 팔로우됨" flushNotification: "알림 이력을 초기화" + exportOfXCompleted: "{x} 추출에 성공했습니다." + login: "로그인 알림이 있습니다" _types: all: "전부" note: "사용자의 새 글" @@ -2329,6 +2417,9 @@ _notification: followRequestAccepted: "팔로우 요청이 승인되었을 때" roleAssigned: "역할이 부여 됨" achievementEarned: "도전 과제 획득" + exportCompleted: "추출을 성공함" + login: "로그인" + test: "알림 테스트" app: "연동된 앱을 통한 알림" _actions: followBack: "팔로우" @@ -2338,6 +2429,7 @@ _deck: alwaysShowMainColumn: "메인 칼럼 항상 표시" columnAlign: "칼럼 정렬" addColumn: "칼럼 추가" + newNoteNotificationSettings: "새 노트 알림 설정" configureColumn: "칼럼 설정" swapLeft: "왼쪽으로 이동" swapRight: "오른쪽으로 이동" @@ -2376,9 +2468,10 @@ _drivecleaner: orderByCreatedAtAsc: "등록일이 오래된 순" _webhookSettings: createWebhook: "Webhook 생성" + modifyWebhook: "Webhook 수정" name: "이름" secret: "시크릿" - events: "Webhook을 실행할 타이밍" + trigger: "트리거" active: "활성화" _events: follow: "누군가를 팔로우했을 때" @@ -2388,6 +2481,27 @@ _webhookSettings: renote: "누군가 내 글을 리노트했을 때" reaction: "누군가 내 노트에 리액션했을 때" mention: "누군가 나를 멘션했을 때" + _systemEvents: + abuseReport: "유저롭" + abuseReportResolved: "받은 신고를 처리했을 때" + userCreated: "유저가 생성되었을 때" + deleteConfirm: "Webhook을 삭제할까요?" + testRemarks: "스위치 오른쪽에 있는 버튼을 클릭하여 더미 데이터를 사용한 테스트용 웹 훅을 보낼 수 있습니다." +_abuseReport: + _notificationRecipient: + createRecipient: "신고 수신자 추가" + modifyRecipient: "신고 수신자 편집" + recipientType: "알림 종류" + _recipientType: + mail: "이메일" + webhook: "Webhook" + _captions: + mail: "모더레이터 권한을 가진 사용자의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)" + webhook: "지정한 SystemWebhook에 알림을 보냅니다 (신고를 받은 때와 해결했을 때에 송신)" + keywords: "키워드" + notifiedUser: "알릴 사용자" + notifiedWebhook: "사용할 Webhook" + deleteConfirm: "수신자를 삭제하시겠습니까?" _moderationLogTypes: createRole: "역할 생성" deleteRole: "역할 삭제" @@ -2403,7 +2517,7 @@ _moderationLogTypes: updateUserNote: "조정 기록 갱신" deleteDriveFile: "파일 삭제" deleteNote: "노트 삭제" - createGlobalAnnouncement: "모든 공지사항 만들기" + createGlobalAnnouncement: "전역 공지사항 생성" createUserAnnouncement: "사용자 공지사항 만들기" updateGlobalAnnouncement: "모든 공지사항 수정" updateUserAnnouncement: "사용자 공지사항 수정" @@ -2416,6 +2530,8 @@ _moderationLogTypes: markSensitiveDriveFile: "파일에 열람주의를 설정" unmarkSensitiveDriveFile: "파일에 열람주의를 해제" resolveAbuseReport: "신고 처리" + forwardAbuseReport: "신고 전달" + updateAbuseReportNote: "신고 조정 노트 갱신" createInvitation: "초대 코드 생성" createAd: "광고 생성" deleteAd: "광고 삭제" @@ -2425,6 +2541,16 @@ _moderationLogTypes: deleteAvatarDecoration: "아바타 장식 삭제" unsetUserAvatar: "유저 아바타 제거" unsetUserBanner: "유저 배너 제거" + createSystemWebhook: "SystemWebhook을 생성" + updateSystemWebhook: "SystemWebhook을 수정" + deleteSystemWebhook: "SystemWebhook을 삭제" + createAbuseReportNotificationRecipient: "신고 알림 수신자 생성" + updateAbuseReportNotificationRecipient: "신고 알림 수신자 편집" + deleteAbuseReportNotificationRecipient: "신고 알림 수신자 삭제" + deleteAccount: "계정을 삭제" + deletePage: "페이지를 삭제" + deleteFlash: "Play를 삭제" + deleteGalleryPost: "갤러리 포스트를 삭제" _fileViewer: title: "파일 상세" type: "파일 유형" @@ -2545,7 +2671,7 @@ _urlPreviewSetting: timeoutDescription: "미리보기를 로딩하는데 걸리는 시간이 정한 시간보다 오래 걸리는 경우, 미리보기를 생성하지 않습니다." maximumContentLength: "Content-Length의 최대치 (byte)" maximumContentLengthDescription: "Content-Length가 이 값을 넘어서면 미리보기를 생성하지 않습니다." - requireContentLength: "Content-Length를 얻었을 때만 미리보기 만들기" + requireContentLength: "Content-Length를 받아온 경우에만 " requireContentLengthDescription: "상대 서버가 Content-Length를 되돌려주지 않는다면 미리보기를 만들지 않습니다." userAgent: "User-Agent" userAgentDescription: "미리보기를 얻을 때 사용한 User-Agent를 설정합니다. 비어 있다면 기본값의 User-Agent를 사용합니다." @@ -2556,3 +2682,22 @@ _mediaControls: pip: "화면 속 화면" playbackRate: "재생 속도" loop: "반복 재생" +_contextMenu: + title: "컨텍스트 메뉴" + app: "애플리케이션" + appWithShift: "Shift 키로 애플리케이션" + native: "브라우저의 UI" +_embedCodeGen: + title: "임베디드 코드를 커스터마이즈" + header: "해더를 표시" + autoload: "자동으로 다음 코드를 실행 (비권장)" + maxHeight: "최대 높이" + maxHeightDescription: "최대 값을 무시하려면 0을 입력하세요. 위젯이 상하로 길어지는 것을 방지하려면, 임의의 값을 입력해 주세요." + maxHeightWarn: "높이 최대 값이 설정되어져 있지 않습니다(0). 의도적으로 설정 하지 않았다면 임의의 값을 설정해주세요." + previewIsNotActual: "미리보기로 표시할 수 있는 크기보다 큽니다. 실제로 넣은 코드의 표시가 다른 경우가 있습니다." + rounded: "외곽선을 둥글게 하기" + border: "외곽선에 테두리를 씌우기" + applyToPreview: "미리보기에 반영" + generateCode: "임베디드 코드를 만들기" + codeGenerated: "코드를 만들었습니다." + codeGeneratedDescription: "만들어진 코드를 웹 사이트에 붙여서 사용하세요." diff --git a/locales/lo-LA.yml b/locales/lo-LA.yml index 087bac3745..b100d0300f 100644 --- a/locales/lo-LA.yml +++ b/locales/lo-LA.yml @@ -18,15 +18,15 @@ enterUsername: "ປ້ອນຊື່ຜູ້ໃຊ້" renotedBy: "Renoted ໂດຍ {user}" noNotes: "ບໍ່ມີ note" noNotifications: "ບໍ່ມີການແຈ້ງເຕືອນ" -instance: "ອີນສະແຕນ" -settings: "ກຳນົດຄ່າ" +instance: "ເຊີຟເວີຣ໌" +settings: "ຕັ້ງຄ່າ" notificationSettings: "ຕັ້ງຄ່າການແຈ້ງເຕືອນ" basicSettings: "ການຕັ້ງຄ່າພື້ນຖານ" otherSettings: "ການຕັ້ງຄ່າອື່ນໆ" -openInWindow: "ເປີດໃນປ່ອງຢ້ຽມ" -profile: "ໂພຼຟາຍ" +openInWindow: "ເປີດໃນ window" +profile: "ໂປຣໄຟລ໌" timeline: "ໄທມ໌ໄລນ໌" -noAccountDescription: "ຜູ້ໃຊ້ນີ້ຍັງບໍ່ໄດ້ຂຽນໃນຊີວະປະຫວັດຂອງເຂົາເຈົ້າເທື່ອ" +noAccountDescription: "ຜູ້ໃຊ້ຄົນນີ້ຍັງບໍ່ໄດ້ຂຽນຄຳແນະນຳໂຕ" login: "ເຂົ້າ​ສູ່​ລະ​ບົບ" loggingIn: "ກຳລັງເຂົ້າສູ່ລະບົບ..." logout: "ອອກ​ຈາກ​ລະ​ບົບ" @@ -37,7 +37,7 @@ users: "ຜູ້ໃຊ້" addUser: "ເພີ່ມຜູ້ໃຊ້" favorite: "ເພີ່ມໃສ່ລາຍການທີ່ມັກ" favorites: "ລາຍການທີ່ມັກ" -unfavorite: "ລຶບອອກຈາກລາຍການທີ່ມັກ" +unfavorite: "ເອົາອອກຈາກລາຍການທີ່ມັກ" favorited: "ເພີ່ມໃສ່ລາຍການທີ່ມັກແລ້ວ" alreadyFavorited: "ເພີ່ມເຂົ້າໃນລາຍການທີ່ມັກແລ້ວ." cantFavorite: "ບໍ່ສາມາດເພີ່ມໃສ່ລາຍການທີ່ມັກໄດ້." @@ -48,41 +48,41 @@ copyLink: "ຄັດລອກລິ້ງ" copyLinkRenote: "ຄັດລອກລິ້ງຂອງ renote" delete: "ລຶບ" deleteAndEdit: "ລຶບ​ແລະ​ແກ້​ໄຂ​" -deleteAndEditConfirm: "ເຈົ້າ​ແນ່​ໃຈ​ບໍ່? ທີ່ທ່ານຕ້ອງການທີ່ຈະລຶບ note ນີ້ ແລະແກ້ໄຂມັນ ທ່ານອາດຈະສູນເສຍ reaction, renote, ແລະການຕອບກັບທັງໝົດ" +deleteAndEditConfirm: "ຕ້ອງການລຶບ note ນີ້ແລະແກ້ໄຂໃໝ່ແມ່ນບໍ່? reaction, renote ແລະການຕອບກັບຕໍ່ note ນີ້ ທັງເບິດຈະຖືກລຶບອອກ" addToList: "ເພີ່ມໃສ່ລາຍຊື່" addToAntenna: "ເພີ່ມໃສ່ເສົາອາກາດ" sendMessage: "ສົ່ງຂໍ້ຄວາມ" -copyRSS: "ສຳເນົາ RSS" -copyUsername: "ສຳເນົາຊື່ຜູ້ໃຊ້" -copyUserId: "ສຳເນົາ ID ຜູ້ໃຊ້" -copyNoteId: "ສຳເນົາ ID ບັນທຶກ" -copyFileId: "ສຳເນົາ ID ໄຟລ໌" -copyFolderId: "ສຳເນົາ ID ໂຟນເດີ" -copyProfileUrl: "ສຳເນົາ URL ໂປຣໄຟລ໌" +copyRSS: "ຄັດລອກ RSS" +copyUsername: "ຄັດລອກຊື່ຜູ້ໃຊ້" +copyUserId: "ຄັດລອກ ID ຜູ້ໃຊ້" +copyNoteId: "ຄັດລອກ ID ຂອງ note" +copyFileId: "ຄັດລອກ ID ໄຟລ໌" +copyFolderId: "ຄັດລອກ ID ໂຟລ໌ເດີຣ໌" +copyProfileUrl: "ຄັດລອກ URL ໂປຣໄຟລ໌" searchUser: "ຄົ້ນຫາຜູ້ໃຊ້" -reply: "ຕອບ​ໄປ​ທີ" +reply: "ຕອບ​ກັບ" loadMore: "ໂຫຼດເພີ່ມເຕີມ" showMore: "ໂຫຼດເພີ່ມເຕີມ" showLess: "ປິດ" -youGotNewFollower: "ໄດ້ຕິດຕາມທ່ານ" -receiveFollowRequest: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ໄດ້ຮັບ" -followRequestAccepted: "ຜູ້ຕິດຕາມໄດ້ຍອມຮັບຄໍາຮ້ອງຂໍຂອງທ່ານ" -mention: "ກ່າວຖືງ" -mentions: "ກ່າວເຖິງ" +youGotNewFollower: "ໄດ້ຕິດຕາມເຈົ້າ" +receiveFollowRequest: "ມີຄຳຂໍຕິດຕາມສົ່ງມາ" +followRequestAccepted: "ການຕິດຕາມໄດ້ຮັບອນຸຍາດແລ້ວ" +mention: "ເວົ້າເຖີງ" +mentions: "ເວົ້າເຖີງເຈົ້າ" directNotes: "ໂພສ Direct note" importAndExport: "ນໍາເຂົ້າ / ສົ່ງອອກ" import: "ນຳເຂົ້າ" export: "ສົ່ງອອກ" files: "ໄຟລ໌" download: "ດາວໂຫລດ" -driveFileDeleteConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບໄຟລ໌ \"{name}\"? note ທີ່ມີໄຟລ໌ແນບນີ້ຈະຖືກລຶບຖິ້ມ" -unfollowConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການເຊົາຕິດຕາມ {name}?" -exportRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການສົ່ງອອກ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ ແລະມັນຈະຖືກເພີ່ມໃສ່ drive ຂອງທ່ານເມື່ອມັນສຳເລັດແລ້ວ" -importRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການນໍາເຂົ້າ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ" +driveFileDeleteConfirm: "ຕ້ອງການລຶບໄຟລ໌ “{name}” ແມ່ນບໍ່? Note ທີ່ແນບມາກັບໄຟລ໌ນີ້ຈະຖືກລຶບອອກ" +unfollowConfirm: "ຕ້ອງການເລີກຕິດຕາມ {name} ແມ່ນບໍ່?" +exportRequested: "ເຈົ້າໄດ້ຮ້ອງຂໍການສົ່ງອອກ ອາດໃຊ້ເວລາຈັກໜ່ອຍ ເມື່ອແລ້ວຈະຖືກເພີ່ມໃສ່ drive" +importRequested: "ເຈົ້າໄດ້ຮ້ອງຂໍການນຳເຂົ້າ ການດຳເນິນການນີ້ອາດໃຊ້ເວລາຈັກໜ່ອຍ" lists: "ລາຍການ" -noLists: "ທ່ານ​ບໍ່​ມີ​ລາຍ​ການ​ໃດໆ​" -note: "ບັນທຶກ" -notes: "ບັນທຶກ" +noLists: "ບໍ່​ມີ​ລາຍ​ການ​ໃດໆ​" +note: "Note" +notes: "Note" following: "ກຳລັງຕິດຕາມ" followers: "ຜູ້ຕິດຕາມ" followsYou: "ຕິດ​ຕາມ​ເຈົ້າ" @@ -124,11 +124,11 @@ reactions: "reaction" attachCancel: "ເອົາໄຟລ໌ແນບ" mute: "ປີດສຽງ" unmute: "ເປີດສຽງ" -block: "ບ໋ອກ" -unblock: "ຍົກເລີກກາຮົບລັອກ" +block: "ບລັອກ" +unblock: "ເລີກບລັອກ" suspend: "ລະງັບ" unsuspend: "ເຊົາ​ລະ​ງັບ" -selectList: "ເລືອກບັນຊີລາຍການ" +selectList: "ເລືອກລາຍຊື່" editList: "ແກ້ໄຂລາຍຊື່" selectChannel: "ເລືອກຊ່ອງ" selectAntenna: "ເລືອກເສົາອາກາດ" @@ -151,30 +151,30 @@ flagShowTimelineRepliesDescription: "ສະແດງການຕອບກັບ autoAcceptFollowed: "ອະນຸມັດອັດຕະໂນມັດຕາມຄຳຮ້ອງຂໍຈາກຜູ້ໃຊ້ທີ່ທ່ານກຳລັງຕິດຕາມຢູ່" addAccount: "ເພີ່ມບັນຊີ" loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ" -showOnRemote: "ເບິ່ງຢູ່ໃນຕົວຢ່າງໄລຍະໄກ" +showOnRemote: "ເບິ່ງໃນເຊີຟເວີຣ໌ໄລຍະໄກ" general: "ທົ່ວໄປ" wallpaper: "ພາບພື້ນຫລັງ" setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ" removeWallpaper: "ລຶບຮູບວໍເປເປີອອກ" searchWith: "ຊອກຫາ: {q}" -youHaveNoLists: "ທ່ານ​ບໍ່​ມີ​ລາຍ​ການ​ໃດໆ​" +youHaveNoLists: "ເຈົ້າບໍ່ມີລາຍຊື່ໃດໆ" proxyAccount: "ບັນຊີພຣັອກຊີ" -host: "ໂຮດສ" +host: "ໂຮສຕ໌" selectUser: "ເລືອກຜູ້ໃຊ້" recipient: "ເຖິງ" annotation: "ຄຳເຫັນ" federation: "ສະຫະພັນ" -instances: "ອີນສະແຕນ" +instances: "ເຊີຟເວີຣ໌" registeredAt: "ລົງທະບຽນຢູ່" storageUsage: "ບ່ອນ​ຈັດ​ເກັບ​ຂໍ້​ມູນທີ່ໃຊ້" -charts: "ອັນດັບເພງ" +charts: "ແຜນພູມ" perHour: "ຕໍ່ຊົ່ວໂມງ" perDay: "ຕໍ່​ມື້" stopActivityDelivery: "ຢຸດເຊົາການສົ່ງກິດຈະກໍາ" blockThisInstance: "ຂັດຂວາງຕົວຢ່າງນີ້" operations: "ການດຳເນີນງານ" software: "ຊອບແວ" -version: "ສະບັບ" +version: "ເວີຣ໌ຊັນ" metadata: "Metadata" withNFiles: "{n} ໄຟລ໌(s)" monitor: "ຈໍພາບ" @@ -199,15 +199,15 @@ federating: "ສະຫະພັນ" blocked: "ບລັອກແລ້ວ " suspended: "ໂຈະ" all: "ທັງໝົດ" -subscribing: "ສະໝັກສະມາຊິກແລັວ" -publishing: "ການ​ພິມ​ເຜີຍ​ແຜ່" +subscribing: "ກຳລັງສະມັກສະມາຊິກ" +publishing: "ກຳລັງ​ເຜີຍ​ແພ່" notResponding: "ບໍ່ຕອບສະໜອງ" -instanceFollowing: "ກຳລັງຕິດຕາມສຸດຕົວຢ່າງ" -instanceFollowers: "ຜູ້ຕິດຕາມຕົວຢ່າງ" -instanceUsers: "ຜູ້​ຊົມ​ໃຊ້​ຂອງ​ຕົວ​ຢ່າງ​ນີ້​" +instanceFollowing: "ກຳລັງຕິດຕາມບົນເຊີຟເວີຣ໌" +instanceFollowers: "ຜູ້ຕິດຕາມຂອງເຊີຟເວີຣ໌" +instanceUsers: "ຜູ້​ໃຊ້​ຂອງ​ເຊີຟເວີຣ໌ນີ້" changePassword: "ປ່ຽນ​ລະ​ຫັດ​ຜ່ານ" security: "ຄວາມປອດໄພ" -retypedNotMatch: "ວັດສະດຸປ້ອນບໍ່ກົງກັນ" +retypedNotMatch: "ປ້ອນຂໍ້ມູນບໍ່ກົງກັນ" currentPassword: "ລະຫັດຜ່ານປະຈຸບັນ" newPassword: "ລະຫັດຜ່ານໃໝ່" newPasswordRetype: "ໃສ່ລະຫັດຜ່ານໃໝ່ອີກເທື່ອໜຶ່ງ" @@ -223,14 +223,14 @@ remove: "ລຶບ" removed: "ລຶບແລ້ວ" resetAreYouSure: "ຣີ​ເຊັດບໍ?" saved: "ບັນທຶກແລ້ວ" -messaging: "ແຊ໋ດ" +messaging: "ແຊັຕ" upload: "ອັບໂຫຼດ" keepOriginalUploading: "ຮັກສາຮູບພາບຕົ້ນສະບັບ" fromDrive: "ຈາກ Drive" fromUrl: "ຈາກ URL" uploadFromUrl: "ອັບໂຫຼດຈາກ URL" uploadFromUrlDescription: "URL ຂອງໄຟລ໌ທີ່ທ່ານຕ້ອງການອັບໂຫລດ" -uploadFromUrlRequested: "ຮ້ອງຂໍການອັບໂຫລດ" +uploadFromUrlRequested: "ຮ້ອງຂໍການອັບໂຫລດແລ້ວ" explore: "ສຳຫຼວດ" messageRead: "ອ່ານແລ້ວ" startMessaging: "ເລີ່ມການສົນທະນາໃໝ່" @@ -244,47 +244,47 @@ images: "ຮູບພາບ" image: "ຮູບພາບ" birthday: "ວັນເກີດ" yearsOld: "{age} ປີ" -registeredDate: "ວັນທີ່ເປັນສະມາຊິກ" +registeredDate: "ວັນທີ່ລົງທະບຽນ" location: "ທີ່ຕັ້ງ" -theme: "ແທ໋ມ" -themeForLightMode: "ຮູບແບບສີສັນເພື່ອໃຊ້ໃນໂໝດແສງ" -themeForDarkMode: "ຮູບແບບສີສັນທີ່ຈະໃຊ້ຢູ່ໃນໂໝດມືດ" +theme: "Theme" +themeForLightMode: "Theme ໃຊ້ໃນໂໝດສະຫວ່າງ" +themeForDarkMode: "Theme ໃຊ້ໃນໂໝດມືດ" light: "ສະຫວ່າງ" dark: "ມືດ" lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ" darkThemes: "ຮູບແບບສີສັນມືດ" syncDeviceDarkMode: "ຊິງຄ໌ໂໝດມືດກັບການຕັ້ງຄ່າທົ່ວອຸປະກອນ" -drive: "ຂັບ" +drive: "Drive" fileName: "ຊື່ໄຟລ໌" selectFile: "ເລືອກໄຟລ໌" selectFiles: "ເລືອກໄຟລ໌" selectFolder: "ເລືອກໂຟລເດີ" selectFolders: "ເລືອກໂຟລເດີ" renameFile: "ປ່ຽນຊື່ໄຟລ໌" -folderName: "ຊື່ໂຟນເດີ" +folderName: "ຊື່ໂຟລເດີຣ໌" createFolder: "​ສ້າງ​ໂຟ​ລ​ເດີ" renameFolder: "ປ່ຽນຊື່ໂຟນເດີນີ້" deleteFolder: "ລົບໂຟ​ລ​ເດີ​" addFile: "ເພີ່ມໄຟລ໌" emptyDrive: "Drive ຂອງທ່ານຫວ່າງເປົ່າ" -emptyFolder: "ໂຟນເດີນີ້ເປົ່າຫວ່າງ" +emptyFolder: "ໂຟລເດີຣ໌ນີ້ວ່າງເປົ່າ" unableToDelete: "ບໍ່​ສາ​ມາດລົບໄດ້" inputNewFileName: "ໃສ່ຊື່ໄຟລ໌ໃໝ່" inputNewDescription: "ໃສ່ຄຳບັນຍາຍໃໝ່" inputNewFolderName: "ໃສ່ຊື່ໂຟນເດີໃໝ່" circularReferenceFolder: "ໂຟນເດີປາຍທາງແມ່ນໂຟນເດີຍ່ອຍຂອງໂຟນເດີທີ່ທ່ານຕ້ອງການຍ້າຍ" rename: "ປ່ຽນຊື່" -doNothing: "ບໍ່ສົນໃຈ" -watch: "ເບິ່ງ" -unwatch: "ຢຸດເບິ່ງ" +doNothing: "ຢ່າມັນ" +watch: "ເພັ່ງເລັງ" +unwatch: "ຢຸດເພັ່ງເລັງ" accept: "ອະນຸຍາດ" reject: "ປະຕິເສດ" normal: "ປົກກະຕິ" instanceName: "ຊື່ເຊີເວີ້" -instanceDescription: "ຄໍາອະທິບາຍຕົວຢ່າງ" +instanceDescription: "ຄຳອະທິບາຍແນະນຳເຊີຟເວີຣ໌" maintainerName: "ຜູ້ດູແລ" -maintainerEmail: "ອີເມວ admin" -tosUrl: "ເງື່ອນໄຂການໃຫ້ບໍລິການ URL" +maintainerEmail: "ອີເມລຜູ້ດູແລ" +tosUrl: " URL ເງື່ອນໄຂການໃຫ້ບໍລິການ" thisYear: "ປີນີ້" thisMonth: "ເດືອນນີ້" today: "ມື້ນີ້" @@ -292,34 +292,34 @@ dayX: "ວັນ {day}" monthX: "ເດືອນ {month}" yearX: "ປີ {year}" pages: "ໜ້າ" -integration: "ຄວາມສຳພັນຂອງ" +integration: "ເຊື່ອມໂຍງ" connectService: "ເຊື່ອມຕໍ່" disconnectService: "ຕັດການເຊື່ອມຕໍ່" enableLocalTimeline: "ເປີດໃຊ້ທາມລາຍທ້ອງຖິ່ນ" enableGlobalTimeline: "ເປີດໃຊ້ທາມລາຍທົ່ວໂລກ" -disablingTimelinesInfo: "ຜູ້ເບິ່ງແຍງລະບົບ ແລະຜູ້ຄວບຄຸມຈະມີການເຂົ້າເຖິງທຸກກຳນົດເວລາ, ເຖິງແມ່ນວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍຕາມ" +disablingTimelinesInfo: "ຜູ້ດູແລລະບບແລະຜູ້ຄວບຄຸມຈະສາມາດເຂົ້າເຖີງໄທມ໌ໄລນ໌ທັ້ງເບີດ ເຖີງວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍ່ຕາມ" registration: "ລົງທະບຽນ" enableRegistration: "ເປີດໃຊ້ການລົງທະບຽນຜູ້ໃຊ້ໃໝ່" invite: "ເຊີນ" -driveCapacityPerLocalAccount: "ຄວາມອາດສາມາດຂັບຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ" -driveCapacityPerRemoteAccount: "ໄດຣຟ໌ຄວາມອາດສາມາດຕໍ່ຜູ້ໃຊ້ທາງໄກ" +driveCapacityPerLocalAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ" +driveCapacityPerRemoteAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ໄລຍະໄກ" basicInfo: "ຂໍ້ມຸນເບື້ອງຕົ້ນ" -pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້" -hcaptchaSiteKey: "ກະແຈໄຊທ໌" -hcaptchaSecretKey: "ກະແຈລັບ" -mcaptchaSiteKey: "ກະແຈໄຊທ໌" -mcaptchaSecretKey: "ກະແຈລັບ" +pinnedNotes: "Note ທີ່ປັກໝຸດໄວ້" +hcaptchaSiteKey: "Site key" +hcaptchaSecretKey: "Secret key" +mcaptchaSiteKey: "Site key" +mcaptchaSecretKey: "Secret Key" recaptcha: "reCAPTCHA" -enableRecaptcha: "ເປີດໃຊ້ງານລີແຄ໋ບຈາ" -recaptchaSiteKey: "ກະແຈໄຊທ໌" -recaptchaSecretKey: "ກະແຈລັບ" -turnstileSiteKey: "ກະແຈໄຊທ໌" -turnstileSecretKey: "ກະແຈລັບ" +enableRecaptcha: "ເປີດໃຊ້ງານ reCAPTCHA" +recaptchaSiteKey: "Site key" +recaptchaSecretKey: "Secret key" +turnstileSiteKey: "Site key" +turnstileSecretKey: "Secret key" name: "ຊື່" userList: "ລາຍການ" about: "ກ່ຽວກັບ" aboutMisskey: "ກ່ຽວກັບ Misskey" -administrator: "ຜູ້ບໍລິຫານ" +administrator: "ຜູ້ດູແລ" token: "ໂທເຄັນ" share: "ແບ່ງປັນ" notFound: "ບໍ່ພົບ" @@ -332,27 +332,27 @@ title: "ຫົວຂໍ້" text: "ຂໍ້ຄວາມ" enable: "ເປີດໃຊ້" next: "ຕໍ່ໄປ" -retype: "ເຂົ້າໄປອີກຄັ້ງ" -quoteAttached: "ວົງຢືມ" +retype: "ລອງພິມລະຫັດອີກເທື່ອໜຶ່ງ" +quoteAttached: "ອ້າງອິງ" invitations: "ເຊີນ" unavailable: "ບໍ່​ສາ​ມາດ​ໃຊ້​ໄດ້" language: "ພາສາ" aboutX: "ກ່ຽວກັບ {x}" emojiStyle: "ຮູບແບບອີໂມຈິ" native: "ພາ​ສາ​ແມ່" -noHistory: "​ບໍ່​ມີ​ລາຍ​ການ​ຢູ່​ບ່ອນ​ນີ້" +noHistory: "​ບໍ່​ມີປະຫວັດ" doing: "ກຳລັງປະມວນຜົນ..." category: "ຫມວດຫມູ່" -tags: "ແທ໋ກ" +tags: "Aliases" createAccount: "ສ້າງບັນຊີ" -existingAccount: "ທີ່ມີຢູ່" -dashboard: "ໜ້າປັດ" +existingAccount: "ບັນຊີທີ່ມີຢູ່ແລ້ວ" +dashboard: "Dashboard" local: "ທ້ອງຖິ່ນ" numberOfDays: "ຈຳນວນມື້" objectStorageBucket: "Bucket" objectStoragePrefix: "Prefix" objectStorageEndpoint: "Endpoint" -objectStorageRegion: "ພາກ​ພື້ນ" +objectStorageRegion: "ພູມິພາກ" deleteAll: "ລຶບທັງໝົດ" sounds: "ສຽງ" sound: "ສຽງ" @@ -365,11 +365,11 @@ state: "ສະຖານະ" sort: "ຈັດຮຽງໂດຍ" ascendingOrder: "ນ້ອຍໄປຫາໃຫຍ່" descendingOrder: "ໃຫຍ່ຫານ້ອຍ" -output: "ຜົນຜະລິດ" -script: "ບົດ​ຄວາມ" +output: "Output" +script: "Script" menu: "ເມນູ" -rearrange: "ຈັດລຽງຄືນ" -poll: "ການພູນ" +rearrange: "ຈັດລຽງໃໝ່" +poll: "Poll" description: "ລາຍລະອຽດ" author: "ຜູ້ຂຽນ" manage: "ການຈັດການ" @@ -383,7 +383,7 @@ permission: "ການອະນຸຍາດ" notificationType: "​ປະເພດການ​ແຈ້ງ​ເຕືອນ" edit: "ແກ້ໄຂ" email: "ອີເມວ" -smtpHost: "ໂຮດສ" +smtpHost: "ໂຮສຕ໌" smtpUser: "ຊື່ຜູ້ໃຊ້" smtpPass: "ລະຫັດຜ່ານ" clearCache: "ລຶບລ້າງແຄສ" @@ -393,12 +393,12 @@ administration: "ການຈັດການ" middle: "ປານກາງ" searchByGoogle: "ຄົ້ນຫາ" file: "ໄຟລ໌" -replies: "ຕອບ​ໄປ​ທີ" +replies: "ຕອບ​ກັບ" renotes: "Renote" _delivery: stop: "ໂຈະ" _type: - none: "ການ​ພິມ​ເຜີຍ​ແຜ່" + none: "ກຳລັງ​ເຜີຍ​ແພ່" _role: _priority: middle: "ປານກາງ" @@ -416,8 +416,8 @@ _sfx: _2fa: renewTOTPCancel: "ບໍ່​ແມ່ນ​ຕອນ​ນີ້" _widgets: - profile: "ໂພຼຟາຍ" - instanceInfo: "ອີນສະແຕນ" + profile: "ໂປຣໄຟລ໌" + instanceInfo: "ຂໍ້ມູລເຊີຟເວີຣ໌" notifications: "ການແຈ້ງເຕືອນ" timeline: "​ເສັ້ນກຳ​ນົດ​ເວ​ລາ​" activity: "ກິດຈະກຳ" @@ -436,28 +436,29 @@ _profile: _exportOrImport: followingList: "ກຳລັງຕິດຕາມ" muteList: "ປີດສຽງ" - blockingList: "ບ໋ອກ" + blockingList: "ບລັອກ" userLists: "ລາຍການ" _charts: federation: "ສະຫະພັນ" _timelines: home: "ໜ້າຫຼັກ" _play: - script: "ບົດ​ຄວາມ" + script: "Script" summary: "ລາຍລະອຽດ" _pages: blocks: image: "ຮູບພາບ" _notification: - youWereFollowed: "ໄດ້ຕິດຕາມທ່ານ" + youWereFollowed: "ໄດ້ຕິດຕາມເຈົ້າ" _types: follow: "ກຳລັງຕິດຕາມ" - mention: "ໄດ້ກ່າວມາ" + mention: "ໄດ້ກ່າວເຖິງ" renote: "Renote" - quote: "ລວມຂໍ້ຄວາມອ້າງອີງ" - reaction: "ປະຕິກິລິຍາ" + quote: "ອ້າງອີງ" + reaction: "Reaction" + login: "ເຂົ້າ​ສູ່​ລະ​ບົບ" _actions: - reply: "ຕອບ​ໄປ​ທີ" + reply: "ຕອບ​ກັບ" renote: "Renote" _deck: _columns: @@ -465,8 +466,12 @@ _deck: tl: "​ເສັ້ນກຳ​ນົດ​ເວ​ລາ​" list: "ລາຍການ" channel: "ຊ່ອງ" - mentions: "ກ່າວເຖິງ" + mentions: "ກ່າວເຖິງເຈົ້າ" _webhookSettings: name: "ຊື່" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "ອີເມວ" _moderationLogTypes: suspend: "ລະງັບ" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index eb48cf72da..dde3035357 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -486,6 +486,7 @@ _notification: renote: "Herdelen" quote: "Quote" reaction: "Reacties" + login: "Inloggen" _actions: reply: "Antwoord" renote: "Herdelen" diff --git a/locales/no-NO.yml b/locales/no-NO.yml index 2b4c9b7776..c5f61db745 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -701,6 +701,7 @@ _notification: renote: "Renotes" quote: "Sitater" reaction: "Reaksjoner" + login: "Logg inn" _actions: reply: "Svar" renote: "Renote" @@ -721,5 +722,9 @@ _deck: direct: "Direkte" _webhookSettings: name: "Navn" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "E-post" _moderationLogTypes: suspend: "Suspender" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 9d75f7a9d7..d7afd57760 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -492,7 +492,6 @@ uiLanguage: "Język wyświetlania UI" aboutX: "O {x}" emojiStyle: "Styl emoji" native: "Natywny" -disableDrawer: "Nie używaj menu w stylu szuflady" showNoteActionsOnlyHover: "Pokazuj akcje notatek tylko po najechaniu myszką" showReactionsCount: "Wyświetl liczbę reakcji na notatkę" noHistory: "Brak historii" @@ -690,10 +689,7 @@ abuseReported: "Twoje zgłoszenie zostało wysłane. Dziękujemy." reporter: "Zgłaszający" reporteeOrigin: "Pochodzenie zgłoszonego" reporterOrigin: "Pochodzenie zgłaszającego" -forwardReport: "Przekaż zgłoszenie do innej instancji" -forwardReportIsAnonymous: "Zamiast twojego konta, anonimowe konto systemowe będzie wyświetlone jako zgłaszający na instancji zdalnej." send: "Wyślij" -abuseMarkAsResolved: "Oznacz zgłoszenie jako rozwiązane" openInNewTab: "Otwórz w nowej karcie" openInSideView: "Otwórz w bocznym widoku" defaultNavigationBehaviour: "Domyślne zachowanie nawigacji" @@ -1209,7 +1205,6 @@ _theme: buttonBg: "Tło przycisku" buttonHoverBg: "Tło przycisku (po najechaniu)" inputBorder: "Obramowanie pola wejścia" - listItemHoverBg: "Tło elementu listy (po najechaniu)" driveFolderBg: "Tło folderu na dysku" wallpaperOverlay: "Nakładka tapety" badge: "Odznaka" @@ -1221,8 +1216,6 @@ _sfx: note: "Wpisy" noteMy: "Mój wpis" notification: "Powiadomienia" - antenna: "Anteny" - channel: "Powiadomienia kanału" _ago: future: "W przyszłości" justNow: "Przed chwilą" @@ -1512,6 +1505,7 @@ _notification: reaction: "Reakcja" receiveFollowRequest: "Otrzymano prośbę o możliwość obserwacji" followRequestAccepted: "Przyjęto prośbę o możliwość obserwacji" + login: "Zaloguj się" app: "Powiadomienia z aplikacji" _actions: followBack: "zaobserwował cię z powrotem" @@ -1546,7 +1540,6 @@ _webhookSettings: createWebhook: "Stwórz Webhook" name: "Nazwa" secret: "Sekret" - events: "Uruchomienie Webhooka" active: "Właczono" _events: follow: "Po zaobserwowaniu użytkownika" @@ -1556,6 +1549,10 @@ _webhookSettings: renote: "Po udostępnieniu wpisu" reaction: "Po otrzymaniu reakcji" mention: "Po zostaniu wspomnianym" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Adres e-mail" _moderationLogTypes: suspend: "Zawieś" resetPassword: "Zresetuj hasło" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index cfc576b6e1..9039fd2141 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -2,14 +2,14 @@ _lang_: "Português" headlineMisskey: "Uma rede ligada por notas" introMisskey: "Bem-vindo! O Misskey é um serviço de microblog descentralizado de código aberto.\nCrie \"notas\" para compartilhar o que está acontecendo agora ou para se expressar com todos à sua volta 📡\nVocê também pode adicionar rapidamente reações às notas de outras pessoas usando a função \"Reações\" 👍\nVamos explorar um novo mundo 🚀" -poweredByMisskeyDescription: "{name} é um dos servidores da plataforma de código aberto Misskey." +poweredByMisskeyDescription: "{name} é uma instância da plataforma de código aberto Misskey." monthAndDay: "{day}/{month}" search: "Pesquisar" notifications: "Notificações" username: "Nome de usuário" password: "Senha" forgotPassword: "Esqueci-me da senha" -fetchingAsApObject: "Buscando no Fediverso" +fetchingAsApObject: "Buscando no Fediverso..." ok: "OK" gotIt: "Entendi" cancel: "Cancelar" @@ -60,6 +60,7 @@ copyFileId: "Copiar o ID do arquivo" copyFolderId: "Copiar o ID da pasta" copyProfileUrl: "Copiar a URL do perfil" searchUser: "Pesquisar usuário" +searchThisUsersNotes: "Pesquisar as notas desse usuário" reply: "Responder" loadMore: "Carregar mais" showMore: "Ver mais" @@ -81,7 +82,7 @@ exportRequested: "A sua solicitação de exportação foi enviada. Isso pode lev importRequested: "A sua solicitação de importação foi enviada. Isso pode levar algum tempo." lists: "Listas" noLists: "Não possui nenhuma lista" -note: "Post" +note: "Publicar" notes: "Posts" following: "Seguindo" followers: "Seguidores" @@ -99,7 +100,7 @@ enterListName: "Insira um nome para a lista" privacy: "Privacidade" makeFollowManuallyApprove: "Pedidos de seguidores precisam ser aprovados" defaultNoteVisibility: "Visibilidade padrão" -follow: "Seguindo" +follow: "Seguir" followRequest: "Enviar pedido de seguidor" followRequests: "Pedidos de seguidor" unfollow: "Deixar de seguir" @@ -108,11 +109,14 @@ enterEmoji: "Inserir emoji" renote: "Repostar" unrenote: "Remover repostagem" renoted: "Repostado" +renotedToX: "Repostar em {name}." cantRenote: "Não é possível repostar esta postagem" cantReRenote: "Não pode repostar este repost" quote: "Citar" inChannelRenote: "Repostar no canal" inChannelQuote: "Citar no canal" +renoteToChannel: "Repostar em canal" +renoteToOtherChannel: "Repostar em outro canal" pinnedNote: "Nota fixada" pinned: "Fixar no perfil" you: "Você" @@ -121,9 +125,16 @@ sensitive: "Conteúdo sensível" add: "Adicionar" reaction: "Reações" reactions: "Reações" +emojiPicker: "Seleção de emoji" +pinnedEmojisForReactionSettingDescription: "Selecionar os emojis que serão fixados e exibidos ao reagir." +pinnedEmojisSettingDescription: "Selecionar os emojis que serão fixos e exibidos na seleção de emoji." +emojiPickerDisplay: "Janela de seleção de emoji" +overwriteFromPinnedEmojisForReaction: "Sobrescrever as opções de reação" +overwriteFromPinnedEmojis: "Sobrescrever as opções gerais" reactionSettingDescription2: "Arraste para reordenar, clique para excluir, pressione + para adicionar." rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas" attachCancel: "Remover anexo" +deleteFile: "Excluir arquivo" markAsSensitive: "Marcar como sensível" unmarkAsSensitive: "Desmarcar como sensível" enterFileName: "Digite o nome do arquivo" @@ -144,6 +155,7 @@ editList: "Editar lista" selectChannel: "Selecionar canal" selectAntenna: "Selecione uma antena" editAntenna: "Editar antena" +createAntenna: "Criar uma antena" selectWidget: "Selecione um widget" editWidgets: "Editar widgets" editWidgetsExit: "Pronto" @@ -170,16 +182,21 @@ addAccount: "Adicionar Conta" reloadAccountsList: "Recarregar lista de contas" loginFailed: "Falha ao logar" showOnRemote: "Exibir remotamente" +continueOnRemote: "" +chooseServerOnMisskeyHub: "Escolher um servidor da Misskey Hub" +specifyServerHost: "Especificar uma instância diretamente" +inputHostName: "Insira o domínio" general: "Geral" wallpaper: "Papel de parede" setWallpaper: "Definir papel de parede" removeWallpaper: "Remover papel de parede" searchWith: "Buscar: {q}" youHaveNoLists: "Não tem nenhuma lista" -followConfirm: "Tem certeza que quer deixar de seguir {name}?" +followConfirm: "Tem certeza que quer seguir {name}?" proxyAccount: "Conta proxy" proxyAccountDescription: "Uma conta de proxy é uma conta que assume o acompanhamento remoto de um usuário sob certas condições específicas. Por exemplo, quando um usuário inclui um usuário remoto em uma lista, mas ninguém na lista está seguindo o usuário remoto, a atividade não é entregue ao servidor. Nesse caso, a conta de proxy entra em ação para seguir o usuário remoto em vez disso." host: "Host" +selectSelf: "Escolher manualmente" selectUser: "Selecionar usuário" recipient: "Destinatário" annotation: "Anotação" @@ -194,6 +211,8 @@ perHour: "Por Hora" perDay: "Por dia" stopActivityDelivery: "Parar a entrega de atividades" blockThisInstance: "Bloquear esta instância" +silenceThisInstance: "Silenciar essa instância" +mediaSilenceThisInstance: "Silenciar a mídia dessa instância" operations: "Operações" software: "Software" version: "Versão" @@ -213,6 +232,10 @@ clearCachedFiles: "Limpar o cache" clearCachedFilesConfirm: "Deseja excluir todos os arquivos remotos em cache?" blockedInstances: "Instância bloqueada" blockedInstancesDescription: "Configure os hosts dos servidores que deseja bloquear, separando-os por quebras de linha. Os servidores bloqueados não poderão interagir com este servidor, incluindo os subdomínios." +silencedInstances: "Instâncias silenciadas" +silencedInstancesDescription: "Liste o nome de hospedagem dos servidores que você deseja silenciar, separados por linha. Todas as contas desses servidores serão silenciada e poderão enviar solicitações para seguir, mas não poderão mencionar usuários locais sem segui-los. Isso não afetará servidores bloqueados." +mediaSilencedInstances: "Instâncias com mídia silenciadas" +mediaSilencedInstancesDescription: "Liste o nome de hospedagem dos servidores cuja mídia você deseja silenciar, separados por linha. Todas as contas desses servidores serão consideradas sensíveis e não poderão utilizar emojis personalizados. Isso não afetará servidores bloqueados." muteAndBlock: "Silenciar e bloquear" mutedUsers: "Usuários silenciados" blockedUsers: "Usuários bloqueados" @@ -249,7 +272,7 @@ more: "Mais!" featured: "Destaques" usernameOrUserId: "Nome de usuário ou ID do usuário" noSuchUser: "Usuário não encontrado" -lookup: "Buscando" +lookup: "Consultar" announcements: "Avisos" imageUrl: "URL da imagem" remove: "Remover" @@ -257,6 +280,7 @@ removed: "Removido" removeAreYouSure: "Deseja excluir \"{x}\"?" deleteAreYouSure: "Deseja excluir \"{x}\"?" resetAreYouSure: "Deseja reiniciar?" +areYouSure: "Tem certeza?" saved: "Salvo" messaging: "Chat" upload: "Fazer upload" @@ -272,7 +296,7 @@ explore: "Explorar" messageRead: "Lida" noMoreHistory: "Não existe histórico anterior" startMessaging: "Iniciar conversação" -nUsersRead: "{n} Pessoas leem" +nUsersRead: "{n} pessoas leram" agreeTo: "Eu concordo com {0}" agree: "Concordar" agreeBelow: "Eu concordo com o seguinte" @@ -288,7 +312,7 @@ birthday: "Aniversário" yearsOld: "{age} anos" registeredDate: "Data de registro" location: "Localização" -theme: "tema" +theme: "Tema" themeForLightMode: "Temas usados ​​no modo de luz" themeForDarkMode: "Temas usados ​​no modo escuro" light: "Claro" @@ -302,11 +326,13 @@ selectFile: "Selecione os arquivos" selectFiles: "Selecione os arquivos" selectFolder: "Selecionar uma pasta" selectFolders: "Selecionar uma pasta" +fileNotSelected: "Nenhuma pasta selecionada" renameFile: "Renomear ficheiro" folderName: "Nome da pasta" createFolder: "Criar pasta" renameFolder: "Renomear Pasta" deleteFolder: "Excluir pasta" +folder: "Pasta" addFile: "Adicionar arquivo" emptyDrive: "O drive está vazio" emptyFolder: "A pasta está vazia" @@ -368,8 +394,11 @@ hcaptcha: "hCaptcha" enableHcaptcha: "Ativar hCaptcha" hcaptchaSiteKey: "Chave do sítio ‘web’" hcaptchaSecretKey: "Chave secreta" +mcaptcha: "mCaptcha" +enableMcaptcha: "Habilitar mCaptcha" mcaptchaSiteKey: "Chave do sítio ‘web’" mcaptchaSecretKey: "Chave secreta" +mcaptchaInstanceUrl: "URL do servidor mCaptcha" recaptcha: "reCAPTCHA" enableRecaptcha: "Habilitar reCAPTCHA" recaptchaSiteKey: "Chave do sítio ‘web’" @@ -385,6 +414,7 @@ name: "Nome" antennaSource: "Origem de entrada" antennaKeywords: "Palavras-chave recebidas" antennaExcludeKeywords: "Palavras-chave negativas" +antennaExcludeBots: "Ignorar contas de bot" antennaKeywordsDescription: "Se você separá-lo com um espaço, será uma especificação AND, e se você separá-lo com uma quebra de linha, será uma especificação OR." notifyAntenna: "Notificar novas notas" withFileAntenna: "Apenas notas com arquivos anexados" @@ -417,6 +447,9 @@ totp: "Aplicativo Autenticador" totpDescription: "Digite a senha de uso único informado pelo aplicativo autenticador" moderator: "Moderador" moderation: "Moderação" +moderationNote: "Nota de moderação" +addModerationNote: "Adicionar nota de moderação" +moderationLogs: "Logs de moderação" nUsersMentioned: "Postado por {n} pessoas" securityKeyAndPasskey: "Chave de segurança / Chave de acesso" securityKey: "Chave de segurança" @@ -449,10 +482,12 @@ retype: "Digite novamente" noteOf: "Publicação de {user}" quoteAttached: "Com citação" quoteQuestion: "Anexar como citação?" +attachAsFileQuestion: "O texto na área de transferência é muito longo. Você gostaria de anexá-lo como um arquivo de texto?" noMessagesYet: "Sem conversas até o momento" newMessageExists: "Há uma nova mensagem" onlyOneFileCanBeAttached: "Apenas um arquivo pode ser anexado a uma mensagem" signinRequired: "É necessário se inscrever ou fazer login antes de continuar" +signinOrContinueOnRemote: "Para continuar, você precisa mover o seu servidor ou entrar/cadastrar-se nesse servidor." invitations: "Convidar" invitationCode: "Código de convite" checking: "Verificando..." @@ -474,8 +509,8 @@ uiLanguage: "Idioma de exibição da interface " aboutX: "Sobre {x}" emojiStyle: "Estilo de emojis" native: "Nativo" -disableDrawer: "Não mostrar o menu em formato de gaveta" showNoteActionsOnlyHover: "Exibir as ações da nota somente ao passar o cursor sobre ela" +showReactionsCount: "Ver o número de reações nas notas" noHistory: "Ainda não há histórico" signinHistory: "Histórico de acesso" enableAdvancedMfm: "Habilitar MFM avançado" @@ -524,10 +559,11 @@ objectStorageUseProxy: "Usar proxy" objectStorageUseProxyDesc: "Se você não usa proxy para conexão de API, desative-o." objectStorageSetPublicRead: "Definir 'public-read' ao fazer o upload" s3ForcePathStyleDesc: "Ao habilitar s3ForcePathStyle, o nome do bucket é especificado como parte do caminho em vez de ser o nome do host na URL. Isso pode ser necessário ao usar serviços auto-hospedados como o Minio." -serverLogs: "Registro do servidor" +serverLogs: "Logs do servidor" deleteAll: "Excluir tudo" showFixedPostForm: "Exibir o formulário de postagem na parte superior da linha do tempo" showFixedPostFormInChannel: "Exibir o campo de postagem na parte superior da linha do tempo (canais)" +withRepliesByDefaultForNewlyFollowed: "Incluir respostas por usuários recém-seguidos na linha do tempo por padrão" newNoteRecived: "Nova nota recebida" sounds: "Sons" sound: "Sons" @@ -537,6 +573,8 @@ showInPage: "Ver na página" popout: "Sair" volume: "Volume" masterVolume: "volume principal" +notUseSound: "Desabilitar som" +useSoundOnlyWhenActive: "Apenas reproduzir sons quando Misskey estiver aberto." details: "Detalhes" chooseEmoji: "Selecione um emoji" unableToProcess: "Não é possível concluir a operação" @@ -557,6 +595,10 @@ output: "Resultado" script: "Script" disablePagesScript: "Desabilitar scripts nas páginas" updateRemoteUser: "Atualizar informações do usuário remoto" +unsetUserAvatar: "Remover avatar" +unsetUserAvatarConfirm: "Você tem certeza de que deseja remover o avatar?" +unsetUserBanner: "Remover banner" +unsetUserBannerConfirm: "Você tem certeza de que deseja remover o banner?" deleteAllFiles: "Excluir todos os arquivos" deleteAllFilesConfirm: "Deseja excluir todos os arquivos?" removeAllFollowing: "Deseja remover todos os seguidores?" @@ -607,6 +649,7 @@ medium: "Médio" small: "Pequeno" generateAccessToken: "Gerar token de acesso" permission: "Permissões" +adminPermission: "Permissões de administrador" enableAll: "Habilitar tudo" disableAll: "Desabilitar tudo" tokenRequested: "Autorização de acesso à conta" @@ -628,6 +671,7 @@ smtpSecure: "Use SSL/TLS implícito para conexões SMTP" smtpSecureInfo: "Desative esta opção ao utilizar STARTTLS." testEmail: "Testar envio de e-mail" wordMute: "Silenciar palavras" +hardWordMute: "SIlenciamento pesado de palavra" regexpError: "Erro na expressão regular" regexpErrorDescription: "Ocorreu um erro na expressão regular na linha {line} da palavra mutada {tab}:" instanceMute: "Instâncias silenciadas" @@ -649,12 +693,13 @@ useGlobalSettingDesc: "Ao ativar, serão utilizadas as configurações de notifi other: "Outros" regenerateLoginToken: "Gerar novo token de login" regenerateLoginTokenDescription: "Gera novamente o token interno usado para o login. Normalmente, isso não é necessário. Ao regenerar, você será desconectado de todos os dispositivos." +theKeywordWhenSearchingForCustomEmoji: "Essa é a palavra-chave ao pesquisar por emojis personalizados" setMultipleBySeparatingWithSpace: "Você pode configurar vários itens separando-os por espaço." fileIdOrUrl: "ID do arquivo ou URL" behavior: "Comportamento" sample: "Exemplo" abuseReports: "Denúncias" -reportAbuse: "Denúncias" +reportAbuse: "Denunciar" reportAbuseRenote: "Reportar repostagem" reportAbuseOf: "Denunciar {name}" fillAbuseReportDescription: "Por favor, forneça detalhes sobre o motivo da denúncia. Se houver uma nota específica envolvida, inclua também a URL dela." @@ -662,10 +707,7 @@ abuseReported: "Denúncia enviada. Obrigado por sua ajuda." reporter: "Denunciante" reporteeOrigin: "Origem da denúncia" reporterOrigin: "Origem do denunciante" -forwardReport: "Encaminhar a denúncia para o servidor remoto" -forwardReportIsAnonymous: "No servidor remoto, suas informações não serão visíveis, e você será apresentado como uma conta do sistema anônima." send: "Enviar" -abuseMarkAsResolved: "Marcar denúncia como resolvida" openInNewTab: "Abrir em nova aba" openInSideView: "Abrir em visão lateral" defaultNavigationBehaviour: "Navegação padrão" @@ -708,6 +750,7 @@ lockedAccountInfo: "Mesmo que você defina a aprovação para seguir, a menos qu alwaysMarkSensitive: "Marcar como sensível por padrão" loadRawImages: "Exibir as imagens originais ao invés de miniaturas" disableShowingAnimatedImages: "Não reproduzir imagens animadas" +highlightSensitiveMedia: "Destacar mídia sensível" verificationEmailSent: "Um e-mail de confirmação foi enviado. Siga o link no e-mail para concluir a verificação." notSet: "Não definido" emailVerified: "O endereço de e-mail foi confirmado" @@ -721,7 +764,7 @@ experimentalFeatures: "Funcionalidades Experimentais" experimental: "Experimental" thisIsExperimentalFeature: "Este é um recurso experimental. As funções podem mudar ou pode não funcionar corretamente." developer: "Programador" -makeExplorable: "Deixe a sua conta mais fácil de encontrar." +makeExplorable: "Deixe a sua conta encontrável em \"Explorar\"." makeExplorableDescription: "Se você desativá-lo, outros usuários não poderão encontrar a sua conta na aba Descoberta." showGapBetweenNotesInTimeline: "Mostrar um espaço entre as notas na linha de tempo" duplicate: "Duplicar" @@ -796,11 +839,12 @@ switchAccount: "Trocar conta" enabled: "Ativado" disabled: "Desativado" quickAction: "Ações rápidas" -user: "Usuários" +user: "Usuário" administration: "Administrar" accounts: "Contas" switch: "Trocar" noMaintainerInformationWarning: "A informação de administrador não foi configurada." +noInquiryUrlWarning: "URL de consulta não está definida" noBotProtectionWarning: "A proteção contra bots não foi configurada." configure: "Configurar" postToGallery: "Criar publicação em galeria" @@ -860,6 +904,8 @@ makeReactionsPublicDescription: "Isto vai deixar o histórico de todas as suas r classic: "Clássico" muteThread: "Silenciar esta conversa" unmuteThread: "Desativar silêncio desta conversa" +followingVisibility: "Visibilidade dos usuários seguidos" +followersVisibility: "Visibilidade dos seguidores" continueThread: "Ver mais desta conversa" deleteAccountConfirm: "Deseja realmente excluir a conta?" incorrectPassword: "Senha inválida." @@ -925,21 +971,33 @@ fast: "Rápido" sensitiveMediaDetection: "Detecção de conteúdo sensível" localOnly: "Apenas local" remoteOnly: "Apenas remoto" +failedToUpload: "Falha ao enviar" +cannotUploadBecauseInappropriate: "Esse arquivo não pôde ser enviado porque partes dele foram detectadas como potencialmente inapropriadas." +cannotUploadBecauseNoFreeSpace: "Envio falhou devido à falta de capacidade no Drive." cannotUploadBecauseExceedsFileSizeLimit: "Não é possível realizar o upload deste arquivo porque ele excede o tamanho máximo permitido." beta: "Beta" enableAutoSensitive: "Marcar automaticamente como conteúdo sensível" enableAutoSensitiveDescription: "Quando disponível, a marcação de mídia sensível será automaticamente atribuído ao conteúdo de mídia usando aprendizado de máquina. Mesmo que você desative essa função, em alguns servidores, isso pode ser configurado automaticamente." activeEmailValidationDescription: "A validação do endereço de e-mail do usuário será realizada de forma mais rigorosa, considerando se é um endereço descartável ou se é possível realizar comunicação efetiva. Se desativado, apenas a validade do formato do endereço será verificada como uma sequência de caracteres." +navbar: "Barra de navegação" shuffle: "Aleatório" account: "Contas" move: "Mover" pushNotification: "Notificações Push" subscribePushNotification: "Ativar notificações push" unsubscribePushNotification: "Desativar notificações push" +pushNotificationAlreadySubscribed: "Notificações push já estão habilitadas" +pushNotificationNotSupported: "Seu navegador ou instância não tem suporte às notificações push" +sendPushNotificationReadMessage: "Apagar notificações push quando elas foram lidas" +sendPushNotificationReadMessageCaption: "Pode aumentar o consumo de energia do dispositivo." +windowMaximize: "Maximizar" windowMinimize: "Minimizar" windowRestore: "Restaurar" caption: "legenda" +loggedInAsBot: "Atualmente conectado como bot" tools: "Ferramentas" +cannotLoad: "Não foi possível carregar" +numberOfProfileView: "Visualizações do perfil" like: "Curtir" unlike: "Remover curtida" numberOfLikes: "Número de curtidas" @@ -948,6 +1006,7 @@ neverShow: "Não exibir novamente" remindMeLater: "Lembrar mais tarde" didYouLikeMisskey: "Você gostou do Misskey?" pleaseDonate: "O Misskey é um software gratuito utilizado por {host}. Para que possamos continuar o desenvolvimento, pedimos que considerem fazer doações. A sua contribuição é muito importante!" +correspondingSourceIsAvailable: "O código-fonte correspondente está disponível em {anchor}" roles: "Cargos" role: "Cargo" noRole: "Nenhum cargo" @@ -957,6 +1016,7 @@ assign: "Atribuir" unassign: "Remover" color: "Cor" manageCustomEmojis: "Gerenciar Emojis customizados" +manageAvatarDecorations: "Gerenciar decorações de avatar" youCannotCreateAnymore: "Você atingiu o limite de criação." cannotPerformTemporary: "Ação temporariamente indisponível" cannotPerformTemporaryDescription: "Esta ação não pôde ser concluída devido ao excesso de pedidos em sucessão. Tente novamente em alguns momentos." @@ -974,218 +1034,635 @@ thisPostMayBeAnnoyingHome: "Postar na linha do tempo inicial" thisPostMayBeAnnoyingCancel: "Cancelar" thisPostMayBeAnnoyingIgnore: "Postar mesmo assim" collapseRenotes: "Ocultar repostagens já visualizadas" +collapseRenotesDescription: "Colapsar notas em que você reagiu ou repostou." internalServerError: "Erro interno de servidor" +internalServerErrorDescription: "Houve um erro inesperado no servidor." +copyErrorInfo: "Copiar detalhes de erro" +joinThisServer: "Cadastrar-se na instância" +exploreOtherServers: "Buscar outra instância" +letsLookAtTimeline: "Dar uma olhada na linha do tempo" +disableFederationConfirm: "Realmente desabilitar a federação?" +disableFederationConfirmWarn: "Mesmo se defederado, publicações continuarão sendo públicas, a menos que seja definido o contrário. Você geralmente não precisa disso." +disableFederationOk: "Desabilitar" +invitationRequiredToRegister: "Essa instância é apenas para convidados. Você precisa inserir um código válido para se cadastrar." emailNotSupported: "O envio de e-mails não é suportado nesta instância" +postToTheChannel: "Publicar ao canal" +cannotBeChangedLater: "Isso não pode ser alterado." +reactionAcceptance: "Aceitação de Reações" likeOnly: "Apenas curtidas" likeOnlyForRemote: "Tudo (somente curtidas remotas)" +nonSensitiveOnly: "Apenas não-sensível" nonSensitiveOnlyForLocalLikeOnlyForRemote: "Apenas não sensíveis (somente curtidas remotas)" rolesAssignedToMe: "Cargos atribuídos a mim" +resetPasswordConfirm: "Deseja realmente mudar a sua senha?" +sensitiveWords: "Palavras sensíveis" +sensitiveWordsDescription: "A visibilidade de todas as notas contendo as palavras configuradas será colocadas como \"Início\" automaticamente. Você pode listar várias delas separando-as por linha." +sensitiveWordsDescription2: "Utilizar espaços irá criar expressões aditivas (AND) e cercar palavras-chave com barras irá transformá-las em expressões regulares (RegEx)" +prohibitedWords: "Palavras proibidas" +prohibitedWordsDescription: "Habilita um erro ao tentar publicar uma nota contendo as palavras escolhidas. Várias palavras podem ser escolhidas, separando-as por linha." +prohibitedWordsDescription2: "Utilizar espaços irá criar expressões aditivas (AND) e cercar palavras-chave com barras irá transformá-las em expressões regulares (RegEx)" +hiddenTags: "Hashtags escondidas" +hiddenTagsDescription: "Selecione tags que não serão exibidas na lista de destaques. Várias tags podem ser escolhidas, separadas por linha." +notesSearchNotAvailable: "A pesquisa de notas está indisponível." +license: "Licença" unfavoriteConfirm: "Deseja realmente remover dos favoritos?" +myClips: "Meus clipes" drivecleaner: "Limpeza do drive" +retryAllQueuesNow: "Tentar novamente todas as pendências" retryAllQueuesConfirmTitle: "Gostaria de tentar novamente agora?" +retryAllQueuesConfirmText: "Isso irá temporariamente aumentar a carga do servidor." +enableChartsForRemoteUser: "Gerar gráficos estatísticos de usuários remotos" +enableChartsForFederatedInstances: "Gerar gráficos estatísticos de instâncias remotas" +showClipButtonInNoteFooter: "Adicionar \"Clip\" ao menu de ação de notas" reactionsDisplaySize: "Tamanho de exibição das reações" +limitWidthOfReaction: "Limita o comprimento máximo de reações e as exibe em tamanho reduzido" +noteIdOrUrl: "ID ou URL de nota" +video: "Vídeo" +videos: "Vídeos" +audio: "Áudio" +audioFiles: "Áudio" +dataSaver: "Economia de Dados" +accountMigration: "Migração da Conta" +accountMoved: "Esse usuário moveu-se para uma nova conta:" +accountMovedShort: "Essa conta foi migrada." +operationForbidden: "Operação proibída" +forceShowAds: "Sempre mostrar propagandas" +addMemo: "Adicionar memorando" +editMemo: "Editar memorando" reactionsList: "Reações" renotesList: "Repostagens" +notificationDisplay: "Notificações" leftTop: "Superior esquerdo" rightTop: "Superior direito" leftBottom: "Inferior esquerdo" rightBottom: "Inferior direito" +stackAxis: "Eixo de empilhamento" vertical: "Vertical" horizontal: "Exibir painel lateral inteiro" position: "Posição" serverRules: "Regras do servidor" +pleaseConfirmBelowBeforeSignup: "Para cadastrar-se no servidor, você precisa ler e concordar como seguinte:" +pleaseAgreeAllToContinue: "Você precisa concordar com todos os campos acima para continuar." continue: "Continuar" +preservedUsernames: "Nomes de usuário reservados" preservedUsernamesDescription: "Liste os nomes de usuário que deseja reservar, separando-os por quebras de linha. Os nomes de usuário especificados aqui não poderão ser utilizados durante a criação de contas. No entanto, esta restrição não se aplica quando a conta é criada por um administrador. Além disso, as contas que já existem não serão afetadas." +createNoteFromTheFile: "Compor nota a partir desse arquivo" archive: "Arquivo" +archived: "Arquivado" +unarchive: "Desarquivar" channelArchiveConfirmTitle: "Deseja realmente arquivar {name}?" +channelArchiveConfirmDescription: "Um canal arquivado não irá aparecer na lista de canais e nem resultados de pesquisa. Novas publicações não poderão mais ser adicionadas." +thisChannelArchived: "Esse canal foi arquivado." +displayOfNote: "Exibição de nota" +initialAccountSetting: "Configuração inicial do perfil" youFollowing: "Seguindo" +preventAiLearning: "Rejeitar uso de Aprendizado de Máquina (IA Generativa)" preventAiLearningDescription: "Solicita-se que o conteúdo de notas e imagens enviadas não seja usado como objeto de aprendizado por sistemas externos de geração de texto ou imagens. Isso é alcançado incluindo a flag 'noai' na resposta HTML. No entanto, o cumprimento dessa solicitação depende do próprio sistema de IA, portanto, não é garantia total de prevenção de aprendizado." options: "Opções" +specifyUser: "Usuário específico" +lookupConfirm: "Deseja buscar?" +openTagPageConfirm: "Deseja abrir a uma página de hashtag?" +specifyHost: "Especificar um hospedeiro" +failedToPreviewUrl: "Não foi possível carregar prévia" +update: "Atualizar" rolesThatCanBeUsedThisEmojiAsReaction: "Cargos que podem utilizar este emoji como reação" rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Se nenhum cargo for especificado, qualquer pessoa pode usar este emoji como reação." rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Estes cargos devem ser públicos." +cancelReactionConfirm: "Realmente excluir a sua reação?" +changeReactionConfirm: "Realmente mudar a sua reação?" +later: "Talvez mais tarde" +goToMisskey: "Ao Misskey" +additionalEmojiDictionary: "Dicionários adicionais de emoji" +installed: "Instalado" +branding: "Marca" +enableServerMachineStats: "Publicar estatísticas do hardware do servidor" +enableIdenticonGeneration: "Habilitar geração de identicon de usuário" +turnOffToImprovePerformance: "Desligar isso pode melhorar o desempenho." +createInviteCode: "Gerar convite" +createWithOptions: "Criar com opções" +createCount: "Número de convites" +inviteCodeCreated: "Convite gerado" +inviteLimitExceeded: "Você excedeu o limite de convites que podem ser gerados." +createLimitRemaining: "Limite de convites: {limit}" +inviteLimitResetCycle: "Esse limite irá tornar-se {limit} em {time}." +expirationDate: "Data de expiração" +noExpirationDate: "Sem expiração" +inviteCodeUsedAt: "Código de convite usado em" +registeredUserUsingInviteCode: "Convite usado por" waitingForMailAuth: "Verificação de e-mail pendente " +inviteCodeCreator: "Convite criado por" +usedAt: "Usado em" +unused: "Não foi usado" +used: "Usado" +expired: "Expirado" +doYouAgree: "Concorda?" +beSureToReadThisAsItIsImportant: "Por favor, leia essa informação importante." +iHaveReadXCarefullyAndAgree: "Eu li o texto \"{x}\" e concordo." +dialog: "Diálogo" icon: "Avatar" +forYou: "Para você" +currentAnnouncements: "Anúncios atuais" +pastAnnouncements: "Anúncios passados" +youHaveUnreadAnnouncements: "Há anúncios não lidos." +useSecurityKey: "Por favor, siga as instruções do seu navegador ou dispositivo para utilizar uma chave de acesso." replies: "Responder" renotes: "Repostar" +loadReplies: "Mostrar respostas" +loadConversation: "Mostrar conversa" +pinnedList: "Lista fixada" keepScreenOn: "Manter a tela do dispositivo sempre ligada" +verifiedLink: "A autoria do link foi verificada" +notifyNotes: "Notificar sobre novas notas" +unnotifyNotes: "Deixar de notificar sobre novas notas" +authentication: "Autenticação" +authenticationRequiredToContinue: "Por favor, autentique-se para continuar" +dateAndTime: "Data e Hora" +showRenotes: "Exibir reposts" +edited: "Editado" +notificationRecieveConfig: "Configurações de Notificação" +mutualFollow: "Seguidor mútuo" +followingOrFollower: "Seguidor ou usuário seguido" +fileAttachedOnly: "Apenas notas com arquivos" +showRepliesToOthersInTimeline: "Mostrar respostas aos outros na linha do tempo" +hideRepliesToOthersInTimeline: "Esconder respostas dos outros na linha do tempo" +showRepliesToOthersInTimelineAll: "Mostrar respostas aos outros, mas apenas de quem você segue, na linha do tempo" +hideRepliesToOthersInTimelineAll: "Esconder respostas de todos que você segue na linha do tempo" +confirmShowRepliesAll: "Essa operação é irreversível. Você gostaria de mostrar respostas a todos que você segue na sua linha do tempo?" +confirmHideRepliesAll: "Essa operação é irreversível. Você gostaria de esconder respostas a todos que você segue na sua linha do tempo?" +externalServices: "Serviços Externos" +sourceCode: "Código-fonte" +sourceCodeIsNotYetProvided: "Código-fonte está indisponível. Contate o administrador para resolver esse problema." +repositoryUrl: "URL do repositório" +repositoryUrlDescription: "Se você estiver utilizando Misskey como está (sem mudanças no código-fonte), insira https://github.com/misskey-dev/misskey" +repositoryUrlOrTarballRequired: "Se você não publicou um repositório, você precisa providenciar uma tarball em seu lugar. Veja .config/example.yml para mais informações." +feedback: "Feedback" +feedbackUrl: "Link para Feedback" +impressum: "Impressum" +impressumUrl: "URL de 'Impressum'" +impressumDescription: "Em alguns países, como a Alemanha, a inclusão de informação de contato do operador de um serviço é legalmente exigida para websites comerciais." +privacyPolicy: "Política de Privacidade" +privacyPolicyUrl: "URL da Política de Privacidade" +tosAndPrivacyPolicy: "Termos de Serviço e Política de Privacidade" +avatarDecorations: "Decorações de avatar" +attach: "Anexar" +detach: "Remover" +detachAll: "Remover Tudo" +angle: "Ângulo" flip: "Inversão" +showAvatarDecorations: "Exibir decorações de avatar" +releaseToRefresh: "Solte para atualizar" +refreshing: "Atualizando..." +pullDownToRefresh: "Puxe para baixo para atualizar" +disableStreamingTimeline: "Desabilitar atualizações em tempo real da linha do tempo" +useGroupedNotifications: "Agrupar notificações" +signupPendingError: "Houve um problema ao verificar o endereço de email. O link pode ter expirado." +cwNotationRequired: "Se \"Esconder conteúdo\" está habilitado, uma descrição deve ser adicionada." +doReaction: "Adicionar reação" +code: "Código" +reloadRequiredToApplySettings: "É necessário reiniciar para aplicar as configurações." +remainingN: "Restante: {n}" +overwriteContentConfirm: "Você tem certeza de que deseja sobrescrever o conteúdo atual?" +seasonalScreenEffect: "Efeito de Tela Sazonal" +decorate: "Decorar" +addMfmFunction: "Adicionar MFM" +enableQuickAddMfmFunction: "Exibir seleção avançada de MFM" +bubbleGame: "Bubble Game" +sfx: "Efeitos Sonoros" +soundWillBePlayed: "Sons serão reproduzidos" +showReplay: "Ver Replay" +replay: "Replay" +replaying: "Mostrando Replay" +endReplay: "Sair do Replay" +copyReplayData: "Copiar dados de Replay" +ranking: "Ranking" lastNDays: "Últimos {n} dias" +backToTitle: "Voltar à página inicial" +hemisphere: "Onde você se localiza" +withSensitive: "Incluir notas com arquivos sensíveis" +userSaysSomethingSensitive: "Publicação de {name} contém conteúdo sensível" +enableHorizontalSwipe: "Arraste para mudar de aba" +loading: "Carregando" surrender: "Cancelar" +gameRetry: "Tentar Novamente" +notUsePleaseLeaveBlank: "Deixe em branco caso inutilizado" +useTotp: "Digite a senha de uso único" +useBackupCode: "Usar códigos de “backup”" +launchApp: "Iniciar aplicação" +useNativeUIForVideoAudioPlayer: "Utilizar UI do navegador ao reproduzir vídeo e áudio" +keepOriginalFilename: "Manter nome original do arquivo" +keepOriginalFilenameDescription: "Se você desabilitar essa opção, os nomes de arquivos serão substituídos por uma sequência aleatória ao enviar arquivos." +noDescription: "Não há descrição" +alwaysConfirmFollow: "Sempre confirmar ao seguir" +inquiry: "Contato" +tryAgain: "Por favor, tente novamente mais tarde" +confirmWhenRevealingSensitiveMedia: "Confirmar ao revelar mídia sensível" +sensitiveMediaRevealConfirm: "Essa mídia pode ser sensível. Deseja revelá-la?" +createdLists: "Listas criadas" +createdAntennas: "Antenas criadas" +clipNoteLimitExceeded: "Não é possível adicionar mais notas ao clipe." _delivery: + status: "Estado de entrega" stop: "Suspenso" + resume: "Continuar entrega" _type: none: "Publicando" + manuallySuspended: "Suspenso manualmente" + goneSuspended: "Servidor foi suspenso devido ao seu apagamento" + autoSuspendedForNotResponding: "Servidor foi suspenso por não responder" +_bubbleGame: + howToPlay: "Como jogar" + hold: "Próximos" + _score: + score: "Pontuação" + scoreYen: "Dinheiro recebido" + highScore: "Melhor pontuação" + maxChain: "Número máximo de encadeamentos" + yen: "{yen} Yen" + estimatedQty: "{qty} Peças" + scoreSweets: "{onigiriQtyWithUnit} Onigiri" + _howToPlay: + section1: "Ajuste a posição e solte o objeto na caixa." + section2: "Quando dois objetos do mesmo tipo tocam-se, eles tornam-se outro objeto e você ganha pontos." + section3: "O jogo acaba quando objetos transbordam da caixa. Busque uma pontuação alta ao fundir objetos enquanto evita transbordar a caixa." +_announcement: + forExistingUsers: "Apenas aos usuários existente" + forExistingUsersDescription: "Se habilitado, esse anúncio será exibido apenas para usuários existentes no tempo de publicação. Se desabilitado, novos usuários também o receberão. " + needConfirmationToRead: "Exigir confirmação de leitura" + needConfirmationToReadDescription: "Um lembrete adicional será exibido para confirmar a leitura do anúncio. Esse anúncio também será excluído de qualquer forma de \"Marcar tudo como lido\"." + end: "Arquivar anúncio" + tooManyActiveAnnouncementDescription: "O excesso de anúncios pode atrapalhar a experiência do usuário. Considere arquivar anúncios obsoletos." + readConfirmTitle: "Marcar como lido?" + readConfirmText: "Isso marcará o conteúdo de \"{title}\" como lido." + shouldNotBeUsedToPresentPermanentInfo: "É preferível utilizar anúncios para publicar informações atuais e de curto prazo, e não informações que serão relevantes por muito tempo." + dialogAnnouncementUxWarn: "O uso de duas ou mais notificações de diálogo simultaneamente pode impactar significativamente a experiência de usuário. Portanto, utilize-as cuidadosamente." + silence: "Sem notificação" + silenceDescription: "Habilitar isso irá pular a notificação desse anúncio e o usuário não precisará lê-lo." _initialAccountSetting: + accountCreated: "A sua conta foi criada com sucesso!" + letsStartAccountSetup: "Em primeiro lugar, vamos configurar o seu perfil." + letsFillYourProfile: "Primeiramente, vamos configurar o seu perfil." + profileSetting: "Configurações do perfil" + privacySetting: "Configurações de privacidade" + theseSettingsCanEditLater: "Você pode alterar estas configurações mais tarde." + youCanEditMoreSettingsInSettingsPageLater: "Há mais configurações na página \"Configurações\". Não se esqueça de visitá-la mais tarde." followUsers: "Siga usuários que lhe interessam para criar a sua linha do tempo." + pushNotificationDescription: "Habilitar notificações push o possibilitará receber notificações de {name} diretamente no seu dispositivo." + initialAccountSettingCompleted: "Configuração de perfil completa!" + haveFun: "Aproveite {name}!" + youCanContinueTutorial: "Você pode iniciar um tutorial de como utilizar {name} (Misskey) ou pode sair da configuração e começar o uso imediatamente." + startTutorial: "Iniciar Tutorial" + skipAreYouSure: "Deseja pular a configuração de perfil?" + laterAreYouSure: "Deseja adiar a configuração de perfil?" +_initialTutorial: + launchTutorial: "Iniciar Tutorial" + title: "Tutorial" + wellDone: "Ótimo!" + skipAreYouSure: "Sair do Tutorial?" + _landing: + title: "Bem-vindo ao Tutorial!" + description: "Aqui, você pode aprender o básico de como usar o Misskey e as suas funções." + _note: + title: "O que é uma Nota?" + description: "Publicações no Misskey chamam-se 'Notas'. Notas são organizadas cronologicamente na linha do tempo e atualizam em tempo real." + reply: "Clique nesse botão para responder a uma mensagem. Também é possível responder respostas, continuando a conversa como uma \"thread\"." + renote: "Você pode compartilhar essa nota na sua linha do tempo. Você também pode citá-la com os seus comentários." + reaction: "Você pode adicionar reações à nota. Mais detalhes serão explicados na próxima página." + menu: "Você pode ver detalhes da nota, copiar links e realizar outras ações." + _reaction: + title: "O que são Reações?" + description: "É possível reagir às notas com diversos emojis. Reações permitem que você expresse sutilezas que não são possíveis apenas com uma curtida." + letsTryReacting: "Reações podem ser adicionadas clicando no botão \"+\". Tente reagir à nota de exemplo." + reactToContinue: "Adicione uma reação para continuar." + reactNotification: "Você receberá notificações em tempo real quando alguém reagir à sua nota." + reactDone: "Você pode desfazer uma reação ao selecionar o botão \"-\"." + _timeline: + title: "O Conceito das Linhas do Tempo" + description1: "Misskey providencia diversas linhas do tempo baseadas na sua utilidade (algumas podem não estar disponíveis a partir das configurações da instância)." + home: "Você pode ver as notas das contas seguidas. " + local: "Você pode ver notas de todos os usuários dessa instância." + social: "Notas da linha do tempo Início e Local serão exibidas." + global: "Você pode ver notas de todos os servidores conectados." + description2: "Você pode alterar dentre as linhas do tempo no todo da tela a qualquer momento." + description3: "Adicionalmente, há \"listas\" e \"canais\". Para mais informações, acesse {link}." + _postNote: + title: "Opções de Postagem de Nota" + description1: "Ao postar uma nota no Misskey, diversas opções estão disponíveis. A ficha de publicação parece com isto: " + _visibility: + description: "Você pode limitar quem vê a sua nota." + public: "Sua nota será visível a todos os usuários." + home: "Publicar apenas na linha do tempo Início. Pessoas visitando seu perfil, seja seguindo ou por um repost poderão vê-los." + followers: "Visível apenas para seguidores. Apenas seguidores podem vê-la e mais ninguém, e ela não pode ser repostada pelos demais." + direct: "Visível apenas para usuários específicos, e o destinatário será notificado. Pode ser usado como uma alternativa às mensagens diretas." + doNotSendConfidencialOnDirect1: "Tenha cuidado ao enviar informações sensíveis!" + doNotSendConfidencialOnDirect2: "Administradores do servidor podem ver o que foi escrito. Cuidado, também, ao enviar notas diretas a usuários de servidores não confiáveis." + localOnly: "Publicar com essa opção não federará a nota com outros servidores. Usuários desses servidores não poderão ver essas notas diretamente, independente das opções de visibilidade acima. " + _cw: + title: "Aviso de Conteúdo" + description: "Ao invés do corpo do texto, o conteúdo escrito na caixa \"anotação\" será exibido. Apertar \"Carregar mais\" irá revelar o corpo." + _exampleNote: + cw: "Isso irá te esfomear!" + note: "Acabei de comer um donut coberto de chocolate! 🍩😋" + useCases: "Isso pode ser usado caso seja exigido, pelas diretrizes do servidor, o cuidado com algum tópico ou ao publicar conteúdo sensível ou spoilers." + _howToMakeAttachmentsSensitive: + title: "Como Marcar Anexos como Sensíveis?" + description: "Para anexos cujo conteúdo é considerado sensível pelas diretrizes do servidor ou quando pretende-se esconder o seu conteúdo, adicione o sinal \"sensível\"." + tryThisFile: "Tente marcar a imagem anexada como sensível!" + _exampleNote: + note: "Opa, me atrapalhei abrindo a tampa do natô..." + method: "Para marcar um anexo como sensível, clique na sua miniatura, abra o menu e clique \"Marcar como sensível\"." + sensitiveSucceeded: "Ao anexar arquivos, por favor atribua uma sensibilidade coerente com as diretrizes da instância." + doItToContinue: "Marque o anexo como sensível para prosseguir." + _done: + title: "Você completou o tutorial! 🎉" + description: "As funções apresentadas aqui são apenas uma pequena parte. Para um conhecimento mais detalhado do uso do Misskey, acesse {link}." +_timelineDescription: + home: "Na linha do tempo Início, você verá notas dos usuários que você segue." + local: "Na linha do tempo Local, você verá notas de todos os usuários da instância." + social: "Na linha do tempo Social, você verá notas do Início e Local." + global: "Na linha do tempo Global, você verá notas de todas as instâncias conectadas." +_serverRules: + description: "Um grupo de regras a ser exibido antes de um cadastro. É recomendado que se faça um resumo dos Termos de Serviço." _serverSettings: iconUrl: "URL do ícone" + appIconDescription: "Especifica o ícone utilizado quando {host} é exibido como um app." + appIconUsageExample: "Exemplo: Como PWA, ou quando exibido num marcador de páginas ou na tela inicial de um celular" + appIconStyleRecommendation: "Como o ícone pode ser cortado para um quadrado ou círculo, é recomendado adicionar um fundo colorido na imagem." + appIconResolutionMustBe: "A resolução mínima é {resolution}." + manifestJsonOverride: "Sobrescrever manifest.json" + shortName: "Abreviação" + shortNameDescription: "Uma abreviação do nome da instância que pode ser exibido caso o nome oficial completo seja muito longo." + fanoutTimelineDescription: "Melhora significativamente a performance do retorno da linha do tempo e reduz o impacto no banco de dados quando habilitado. Em contrapartida, o uso de memória do Redis aumentará. Considere desabilitar em casos de baixa disponibilidade de memória ou instabilidade do servidor." + fanoutTimelineDbFallback: "\"Fallback\" ao banco de dados" + fanoutTimelineDbFallbackDescription: "Quando habilitado, a linha do tempo irá recuar ao banco de dados caso consultas adicionais sejam feitas e ela não estiver em cache. Quando desabilitado, o impacto no servidor será reduzido ao eliminar o recuo, mas limita a quantidade de linhas do tempo que podem ser recebidas." + inquiryUrl: "URL de inquérito" + inquiryUrlDescription: "Especifique um URL para um formulário de inquérito para a administração ou uma página web com informações de contato." _accountMigration: + moveFrom: "Migrar outra conta para essa" + moveFromSub: "Criar um 'alias' a outra conta" + moveFromLabel: "Conta original #{n}" moveFromDescription: "Se você deseja migrar de outra conta para esta, é necessário criar um alias aqui. Por favor, insira a conta de origem da migração no seguinte formato: @username@server.example.com. Para excluir o alias, deixe o campo em branco e clique em salvar (não recomendado)." + moveTo: "Migrar dessa conta para outra" + moveToLabel: "Conta para a qual se mover:" + moveCannotBeUndone: "A migração de conta não pode ser desfeita." moveAccountDescription: "Você está migrando para uma nova conta.\n ・Seus seguidores irão automaticamente seguir a nova conta.\n ・Todas as suas conexões de seguidores nesta conta serão removidas.\n ・Você não poderá mais criar novas notas nesta conta.\n\nA migração dos seguidores é automática, mas a migração das pessoas que você segue deve ser feita manualmente. Antes de migrar, exporte quem você está seguindo nesta conta e, assim que migrar, importe essa lista na nova conta.\nO mesmo se aplica para listas, silenciamentos e bloqueios, que também devem ser migrados manualmente.\n\n(Esta descrição se refere ao comportamento do servidor Misskey v13.12.0 ou posterior. Outros softwares ActivityPub, como Mastodon, podem ter comportamentos diferentes.)" moveAccountHowTo: "Para realizar a migração da conta, primeiro crie um alias para esta conta no destino da migração. Após criar o alias, insira a conta de destino da migração no seguinte formato: @username@server.example.com." + startMigration: "Migrar" migrationConfirm: "Tem certeza de que deseja migrar esta conta para '{account}'? Uma vez migrada, não poderá ser desfeita e não será possível usar esta conta novamente em seu estado original." + movedAndCannotBeUndone: "Essa conta foi migrada. A migração não pode ser desfeita." postMigrationNote: "A remoção dos seguidores desta conta será realizada 24 horas após a operação de migração. O número de seguidores e seguidos desta conta se tornará zero. Os seguidores não serão removidos, portanto, eles continuarão a ver as postagens destinadas aos seguidores desta conta." + movedTo: "Conta para a qual se mover:" _achievements: earnedAt: "Data de aquisição" _types: _notes1: title: "Configurando o meu misskey" - description: "Postou uma nota pela primeira vez" + description: "Poste uma nota pela primeira vez" flavor: "Divirta-se com o Misskey!" _notes10: title: "Algumas notas" - description: "Postou 10 notas" + description: "Poste 10 notas" _notes100: title: "Um monte de notas" - description: "Postou 100 notas" + description: "Poste 100 notas" _notes500: title: "Coberto por notas" - description: "Postou 500 notas" + description: "Poste 500 notas" _notes1000: title: "Uma montanha de notas" - description: "Postou 1000 notas" + description: "Poste 1 000 notas" _notes5000: title: "Enxurrada de notas" - description: "Postou 5000 notas" + description: "Poste 5000 notas" _notes10000: - title: "Super nota" - description: "Postou 10000 notas" + title: "Supernota" + description: "Poste 10 000 notas" _notes20000: title: "Preciso... de mais... notas..." - description: "Postou 20000 notas" + description: "Poste 20 000 notas" _notes30000: title: "Notas, Notas, NOTAS!" - description: "Postou 30000 notas" + description: "Poste 30 000 notas" _notes40000: title: "Fábrica de notas" - description: "Postou 40000 notas" + description: "Poste 40 000 notas" _notes50000: title: "Planeta de notas" - description: "Postou 50000 notas" + description: "Poste 50 000 notas" _notes60000: title: "Quasar de notas" - description: "Postou 60000 notas" + description: "Poste 60 000 notas" _notes70000: title: "Buraco negro de notas" - description: "Postou 70000 notas" + description: "Poste 70 000 notas" _notes80000: title: "Galáxia de notas" - description: "Postou 80000 notas" + description: "Poste 80 000 notas" _notes90000: title: "Universo de notas" - description: "Postou 90000 notas" + description: "Poste 90 000 notas" _notes100000: title: "ALL YOUR NOTE ARE BELONG TO US" - description: "Postou 100000 notas" + description: "Poste 100 000 notas" flavor: "Você realmente tem muita coisa para escrever" _login3: title: "Iniciante I" - description: "Fez login por um total de 3 dias" + description: "Faça login por um total de 3 dias" flavor: "De hoje em diante, me chame apenas de Misskist" _login7: title: "Iniciante II" - description: "Fez login por um total de 7 dias" + description: "Faça login por um total de 7 dias" flavor: "Pegando o jeito da coisa?" _login15: title: "Iniciante III" - description: "Fez login por um total de 15 dias" + description: "Faça login por um total de 15 dias" _login30: title: "Misskist I" - description: "Fez login por um total de 30 dias" + description: "Faça login por um total de 30 dias" _login60: title: "Misskist II" - description: "Fez login por um total de 60 dias" + description: "Faça login por um total de 60 dias" _login100: title: "Misskist III" - description: "Fez login por um total de 100 dias" + description: "Faça login por um total de 100 dias" flavor: "Misskist violento" _login200: title: "Freguês I" - description: "Fez login por um total de 200 dias" + description: "Faça login por um total de 200 dias" _login300: title: "Freguês II" - description: "Fez login por um total de 300 dias" + description: "Faça login por um total de 300 dias" _login400: title: "Freguês III" - description: "Fez login por um total de 400 dias" + description: "Faça login por um total de 400 dias" _login500: title: "Veterano I" - description: "Fez login por um total de 500 dias" + description: "Faça login por um total de 500 dias" flavor: "Cavalheiros, tudo o que peço são notas" _login600: title: "Veterano II" - description: "Fez login por um total de 600 dias" + description: "Faça login por um total de 600 dias" _login700: title: "Veterano III" - description: "Fez login por um total de 700 dias" + description: "Faça login por um total de 700 dias" _login800: - title: "Mestre das notas I" - description: "Fez login por um total de 800 dias" + title: "Mestre das Notas I" + description: "Faça login por um total de 800 dias" _login900: - title: "Mestre das notas II" - description: "Fez login por um total de 900 dias" + title: "Mestre das Notas II" + description: "Faça login por um total de 900 dias" _login1000: - title: "Mestre das notas III" - description: "Fez login por um total de 1000 dias" + title: "Mestre das Notas III" + description: "Faça login por um total de 1 000 dias" flavor: "Obrigado por utilizar o Misskey!" _noteClipped1: - title: "Não posso deixar de adicionar ao clipe" - description: "Adicionou a um clipe a sua primeira nota" + title: "Preciso... clipar..." + description: "Adicione a um clipe a sua primeira nota" _noteFavorited1: - title: "Astrônomo amador" - description: "Adicionou uma nota aos favoritos pela primeira vez" + title: "Astrônomo Amador" + description: "Adicione uma nota aos favoritos pela primeira vez" _myNoteFavorited1: title: "Cabeça nas estrelas" - description: "Teve uma das suas notas adicionada aos favoritos de alguém" + description: "Tenha uma das suas notas adicionada aos favoritos de alguém" _profileFilled: - title: "Tudo pronto" - description: "Configurou o seu perfil" + title: "Tudo Pronto" + description: "Configure o seu perfil" _markedAsCat: title: "Eu Sou Um Gato" - description: "Marcou a sua conta como um gato" + description: "Marque a sua conta como um gato" flavor: "Ainda não tenho um nome." _following1: title: "Primeira vez seguindo alguém" - description: "Seguiu um usuário pela primeira vez" + description: "Siga um usuário pela primeira vez" _following10: title: "Circulando, circulando" - description: "Seguiu 10 usuários" + description: "Siga 10 usuários" _following50: title: "Muitos amigos" - description: "Seguiu 50 usuários" + description: "Siga 50 usuários" _following100: - title: "100 amigos" - description: "Seguiu 100 usuários" + title: "100 Amigos" + description: "Siga 100 usuários" _following300: title: "Sobrecarga de amigos" - description: "Seguiu 300 usuários" + description: "Siga 300 usuários" _followers1: title: "Primeiro seguidor" - description: "Ganhou o seu primeiro seguidor" + description: "Ganhe o seu primeiro seguidor" _followers10: title: "Sigam-me os bons!" - description: "Ganhou 10 seguidores" + description: "Ganhe 10 seguidores" _followers50: title: "Aos montes" - description: "Ganhou 50 seguidores" + description: "Ganhe 50 seguidores" _followers100: title: "Popular" - description: "Ganhou 100 seguidores" + description: "Ganhe 100 seguidores" _followers300: title: "Em fila única, por favor" - description: "Ganhou 300 seguidores" + description: "Ganhe 300 seguidores" _followers500: title: "Torre de celular" - description: "Ganhou 500 seguidores" + description: "Ganhe 500 seguidores" _followers1000: title: "Influencer" - description: "Ganhou 1000 seguidores" + description: "Ganhe 1 000 seguidores" + _collectAchievements30: + title: "Coletor de Conquistas" + description: "Ganhe 30 conquistas" + _viewAchievements3min: + title: "Curte Conquistas" + description: "Olhe para a sua lista de conquistas por pelo menos 3 minutos" + _iLoveMisskey: + title: "Eu Amo Misskey" + description: "Poste \"I ❤ #Misskey\"" + flavor: "A equipe de desenvolvimento do Misskey aprecia profundamente o seu apoio!" + _foundTreasure: + title: "Caça ao Tesouro" + description: "Você achou o tesouro escondido" + _client30min: + title: "Pausinha" + description: "Deixe o Misskey aberto por pelo menos 30 minutos" + _client60min: + title: "Sem falta" + description: "Deixe o Misskey aberto por pelo menos 60 minutos" _noteDeletedWithin1min: title: "Deixa pra lá" - description: "Excluí a postagem dentro de 1 minuto após ter publicado" + description: "Exclua a postagem dentro de 1 minuto após a ter publicado" + _postedAtLateNight: + title: "Noturno" + description: "Poste uma nota tarde da noite" + flavor: "Tá na hora de ir dormir." + _postedAt0min0sec: + title: "Relógio Falante" + description: "Poste uma nota à meia-noite em ponto" + flavor: "Tic-Tac-Tic-Tac" + _selfQuote: + title: "Autorreferência" + description: "Cite sua própria nota" + _htl20npm: + title: "Linha do Tempo Fluida" + description: "Faça a velocidade da linha do tempo exceder 20 npm (notas por minuto)" + _viewInstanceChart: + title: "Analista" + description: "Veja os infográficos da instância" + _outputHelloWorldOnScratchpad: + title: "Olá, Mundo!" + description: "Produza \"hello world\" no Scratchpad" + _open3windows: + title: "Múlti-Janelas" + description: "Tenha ao mínimo 3 janelas abertas simultaneamente." _driveFolderCircularReference: title: "Referência circular" + description: "Tente criar uma pasta recursiva no Drive." + _reactWithoutRead: + title: "Você leu tudo isso?" + description: "Reaja a uma nota com mais de 100 caracteres dentro de 3 segundos após a sua publicação." + _clickedClickHere: + title: "Clique aqui" + description: "Você clicou aqui" + _justPlainLucky: + title: "Pura Sorte" + description: "Tem uma chance de ser obtido com uma probabilidade de 0.005% a cada 10 segundos." + _setNameToSyuilo: + title: "Complexo de Deus" + description: "Colocar seu nome como \"syuilo\"" + _passedSinceAccountCreated1: + title: "Aniversário de Um Ano" + description: "Um ano passou-se desde a criação da conta" + _passedSinceAccountCreated2: + title: "Aniversário de Dois Anos" + description: "Dois anos passaram-se desde a criação da conta" + _passedSinceAccountCreated3: + title: "Aniversário de Três Anos" + description: "Três anos passaram-se desde a criação da conta" + _loggedInOnBirthday: + title: "Feliz Aniversário" + description: "Entre no dia do seu aniversário" + _loggedInOnNewYearsDay: + title: "Feliz Ano Novo!" + description: "Entre no primeiro dia do ano" + flavor: "Para outro ótimo ano nessa instância" + _cookieClicked: + title: "Um jogo onde você clica em cookies" + description: "Clicou o cookie" + flavor: "Pera, você tá no website correto?" + _brainDiver: + title: "Brain Diver" + description: "Poste o link do Brain Diver" + flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "Teste de Transbordamento" + description: "Ative o teste de notificações repetidamente dentro de um curto período de tempo" + _tutorialCompleted: + title: "Diploma de Ensino Fundamental Misskey" + description: "Complete o tutorial" + _bubbleGameExplodingHead: + title: "🤯" + description: "O maior objeto no Bubble Game" + _bubbleGameDoubleExplodingHead: + title: "🤯 Duplo" + description: "Dois dos maiores objetos do Bubble Game ao mesmo tempo." + flavor: "Dá para encher uma lancheira com esses 🤯🤯." _role: new: "Novo cargo" edit: "Editar cargo" @@ -1195,8 +1672,10 @@ _role: descriptionOfPermission: "Moderador permite que você execute operações básicas relacionadas à moderação.\nAdministradores podem alterar todas as configurações do servidor." assignTarget: "Atribuir" descriptionOfAssignTarget: "Manual para gerenciar manualmente quem está incluído neste cargo.\nCondicional define uma condição e os usuários que corresponderem a ela serão incluídos automaticamente." - manual: "Documentação" + manual: "Manual" + manualRoles: "Cargos manuais" conditional: "Condicional" + conditionalRoles: "Cargos condicionais" condition: "Condição" isConditionalRole: "Este é um cargo condicional." isPublic: "Cargo público" @@ -1224,13 +1703,16 @@ _role: gtlAvailable: "Visualizar Linha do Tempo Global" ltlAvailable: "Visualizar Linha do Tempo Local" canPublicNote: "Permitir postagem pública" + mentionMax: "Número máximo de menções em uma nota" canInvite: "Permitir a criação de códigos de convites para a instância" inviteLimit: "Limite de códigos de convite" inviteLimitCycle: "Intervalo de emissão do código de convite" inviteExpirationTime: "Prazo de validade do código de convite" canManageCustomEmojis: "Permitir gerenciar emojis personalizados" + canManageAvatarDecorations: "Gerenciar decorações de avatar" driveCapacity: "Capacidade do drive" alwaysMarkNsfw: "Sempre marcar arquivos como NSFW" + canUpdateBioMedia: "Permitir a edição de ícone ou imagem do banner." pinMax: "Número máximo de notas fixadas" antennaMax: "Número máximo de antenas" wordMuteMax: "Número máximo de caracteres nas palavras silenciadas" @@ -1243,9 +1725,17 @@ _role: descriptionOfRateLimitFactor: "Valores menores são menos restritivos, valores maiores são mais restritivos." canHideAds: "Permitir ocultar anúncios" canSearchNotes: "Permitir a busca de notas" + canUseTranslator: "Uso do tradutor" + avatarDecorationLimit: "Número máximo de decorações de avatar que podem ser aplicadas" _condition: + roleAssignedTo: "Atribuído a cargos manuais" isLocal: "Usuário local" isRemote: "Usuário remoto" + isCat: "Usuários Gatinho" + isBot: "Usuários Bot" + isSuspended: "Usuário suspenso" + isLocked: "Contas privadas" + isExplorable: "Encontrável em \"Explorar\"" createdLessThan: "Menos de X passados desde a criação da conta" createdMoreThan: "Mais de X passados desde a criação da conta" followersLessThanOrEq: "Possui X ou menos seguidores" @@ -1259,13 +1749,19 @@ _role: not: "Não ~ (Condicional)" _sensitiveMediaDetection: description: "Use o aprendizado de máquina para detectar automaticamente mídias sensíveis para moderação. Isso pode aumentar ligeiramente a carga no servidor." + sensitivity: "Detecção de sensibilidade" sensitivityDescription: "Ao reduzir a sensibilidade, as detecções incorretas (falsos positivos) diminuem. Ao aumentar a sensibilidade, as falhas de detecção (falsos negativos) diminuem." + setSensitiveFlagAutomatically: "Marcar como sensível" + setSensitiveFlagAutomaticallyDescription: "Os resultados da detecção interna serão mantidos mesmo se essa opção estiver desligada." + analyzeVideos: "Habilitar análise de vídeos" + analyzeVideosDescription: "Analisa vídeos em adição a imagens. Isso irá aumentar levemente a carga do servidor." _emailUnavailable: used: "O endereço de e-mail informado já está sendo utilizado" format: "Formado de e-mail inválido" disposable: "Endereços de e-mail descartáveis não devem ser utilizados" mx: "O servidor de informado é inválido" smtp: "O servidor de e-mail não está respondendo" + banned: "Você não pode se cadastrar com esse endereço de email" _ffVisibility: public: "Público" followers: "Visível apenas para seguidores" @@ -1285,10 +1781,17 @@ _ad: back: "Voltar" reduceFrequencyOfThisAd: "Diminuir frequência deste anúncio" hide: "Não exibir anúncios" + timezoneinfo: "O dia da semana é determinado pelo fuso horário do servidor." + adsSettings: "Configurações de propaganda" + notesPerOneAd: "Intervalo de notas entre o anúncio nas atualizações em tempo real." + setZeroToDisable: "Selecione o valor 0 para desabilitar anúncios nas atualizações em tempo real." + adsTooClose: "O intervalo atual de anúncio pode impactar negativamente a experiência de usuário por ser muito baixo." _forgotPassword: enterEmail: "Por favor, insira o endereço de e-mail usado no cadastro de sua conta. Um link para redefinição de senha será enviado para esse endereço." ifNoEmail: "Caso você não tenha registrado um endereço de e-mail, por favor, entre em contato com o administrador." + contactAdmin: "Essa instância não possui suporte ao uso de endereços de email, contate seu administrador para mudar a sua senha." _gallery: + my: "Minha Galeria" liked: "Postagens curtidas" like: "Curtir" unlike: "Remover curtida" @@ -1297,40 +1800,223 @@ _email: title: "Você tem um novo seguidor" _receiveFollowRequest: title: "Você recebeu um pedido de seguidor" +_plugin: + install: "Instalar plugins" + installWarn: "Por favor, não instale plugins duvidosos." + manage: "Gerenciar plugins" + viewSource: "Ver código-fonte" + viewLog: "Mostrar registo" _preferencesBackups: + list: "Backups criados" + saveNew: "Salvar novo backup" + loadFile: "Carregar de arquivo" + apply: "Aplicar a este dispositivo" + save: "Salvar mudanças" + inputName: "Insira um nome para esse backup" cannotSave: "Não foi possível salvar" + nameAlreadyExists: "Um backup chamado \"{name}\" já existe. Por favor, insira outro nome." applyConfirm: "Deseja aplicar o backup '{name}' ao dispositivo atual? As configurações atuais do dispositivo serão perdidas." + saveConfirm: "Salvar backup como \"{name}\"?" deleteConfirm: "Deseja excluir {name}?" + renameConfirm: "Renomear esse backup de \"{old}\" para \"{new}\"?" + noBackups: "Não há backups. Você pode configurar suas configurações de cliente nesse servidor ao selecionar \"Criar novo backup\"." + createdAt: "Criado em: {date} {time}" + updatedAt: "Atualizado em: {date} {time}" cannotLoad: "Não foi possível carregar" + invalidFile: "Formato de arquivo inválido" +_registry: + scope: "Escopo" + key: "Chave" + keys: "Chave" + domain: "Domínio" + createKey: "Criar chave" +_aboutMisskey: + about: "Misskey é um software de código aberto desenvolvido por syulio desde 2014." + contributors: "Contribuidores principais" + allContributors: "Todos os contribuidores" + source: "Código-fonte" + original: "Original" + thisIsModifiedVersion: "{name} utiliza uma versão modificada do Misskey original." + translation: "Traduza o Misskey" + donate: "Doe para o Misskey" + morePatrons: "Nós apreciamos o apoio de vários outros apoiadores não listados aqui. Obrigado! 🥰" + patrons: "Apoiadores" + projectMembers: "Membros do projeto" +_displayOfSensitiveMedia: + respect: "Esconder mídia marcada como sensível" + ignore: "Exibir mídia marcada como sensível" + force: "Esconder toda mídia" +_instanceTicker: + none: "Nunca mostrar" + remote: "Mostrar para usuários remotos" + always: "Sempre mostrar" +_serverDisconnectedBehavior: + reload: "Recarregar automaticamente" + dialog: "Exibir diálogo de aviso de conteúdo" + quiet: "Exibir aviso de conteúdo discreto" _channel: + create: "Criar canal" + edit: "Editar canal" + setBanner: "Definir banner" + removeBanner: "Remover banner" featured: "Destaques" + owned: "Autoral" following: "Seguindo" usersCount: "{n} usuários ativos" notesCount: "{n} notas" nameAndDescription: "Nome e descrição" + nameOnly: "Apenas o nome" + allowRenoteToExternal: "Permitir repostagens e citações de fora do canal" _menuDisplay: sideFull: "Exibir painel lateral inteiro" + sideIcon: "Lateral (Ícones)" top: "Exibir barra superior" hide: "Ocultar" +_wordMute: + muteWords: "Palavras silenciadas" + muteWordsDescription: "Separe com espaços para uma condicional AND (&&) ou por linha para uma condicional OR (||)." + muteWordsDescription2: "Cercar palavras-chave com barras para usar expressões regulares (RegEx)." _instanceMute: instanceMuteDescription: "Todas as notas e repostagens do servidor configurado serão silenciados, incluindo respostas aos usuários do servidor mutado." + instanceMuteDescription2: "Separar por linha" + title: "Esconder notas das instâncias listadas. " + heading: "Lista de instâncias a serem silenciadas" _theme: + explore: "Explorar Temas" + install: "Instalar um tema" + manage: "Gerenciar temas" + code: "Código do tema" description: "Descrição" + installed: "{name} foi instalado" + installedThemes: "Temas instalados" + builtinThemes: "Temas nativos" + alreadyInstalled: "Esse tema já foi instalado" + invalid: "O formato desse tema é invalido" + make: "Fazer um tema" + base: "Base" + addConstant: "Adicionar constante" + constant: "Constante" + defaultValue: "Valor padrão" + color: "Cor" + refProp: "Referenciar uma propriedade" + refConst: "Referenciar uma constante" + key: "Chave" + func: "Funções" + funcKind: "Tipo de função" + argument: "Argumento" + basedProp: "Propriedade referenciada" alpha: "Opacidade" + darken: "Escurecer" + lighten: "Esclarecer" + inputConstantName: "Insira um nome para essa constante" + importInfo: "Se você inserir o código do tema aqui, você pode importá-lo no editor de temas" deleteConstantConfirm: "Confirma a exclusão da constante {const}?" keys: + accent: "Cor de destaque" + bg: "Plano de fundo" + fg: "Texto" + focus: "Foco" + indicator: "Indicador" + panel: "Painel" + shadow: "Sombra" + header: "Cabeçalho" + navBg: "Plano de fundo da barra lateral" + navFg: "Texto da barra lateral" + navHoverFg: "Texto da coluna lateral (Selecionado)" + navActive: "Texto da coluna lateral (Ativa)" + navIndicator: "Indicador da coluna lateral" + link: "Link" + hashtag: "Hashtag" mention: "Menção" + mentionMe: "Menciona (a mim)" renote: "Repostar" + modalBg: "Plano de fundo modal" divider: "Separador" + scrollbarHandle: "Alça da barra de rolagem (Selecionada)" + scrollbarHandleHover: "Alça da barra de rolagem (Selecionada)" + dateLabelFg: "Texto do rótulo de data" + infoBg: "Plano de fundo de informações" + infoFg: "Texto de informações" + infoWarnBg: "Plano de fundo de avisos" + infoWarnFg: "Texto de avisos" + toastBg: "Plano de fundo de notificações" + toastFg: "Texto da notificação" + buttonBg: "Plano de fundo de botão" + buttonHoverBg: "Plano de fundo de botão (Selecionado)" + inputBorder: "Borda de campo digitável" + driveFolderBg: "Plano de fundo da pasta no Drive" + wallpaperOverlay: "Sobreposição do papel de parede." + badge: "Emblema" + messageBg: "Plano de fundo do chat" + accentDarken: "Cor de destaque (Escurecida)" + accentLighten: "Cor de destaque (Esclarecida)" + fgHighlighted: "Texto Destacado" _sfx: note: "Posts" + noteMy: "Própria nota" notification: "Notificações" + reaction: "Ao selecionar uma reação" +_soundSettings: + driveFile: "Usar um arquivo de áudio do Drive." + driveFileWarn: "Selecione um arquivo de áudio do Drive." + driveFileTypeWarn: "Esse arquivo não é compatível" + driveFileTypeWarnDescription: "Selecione um arquivo de áudio" + driveFileDurationWarn: "O áudio é muito longo." + driveFileDurationWarnDescription: "Áudios longos podem atrapalhar o funcionamento do Misskey. Deseja continuar?" + driveFileError: "Não foi possível carregar o som. Por favor, altere a configuração." _ago: + future: "Futuro" + justNow: "Agora mesmo" + secondsAgo: "{n}s atrás" + minutesAgo: "{n}m atrás" + hoursAgo: "{n}h atrás" + daysAgo: "{n}d atrás" + weeksAgo: "{n} semanas atrás" + monthsAgo: "{n} meses atrás" + yearsAgo: "{n} anos atrás" invalid: "Não há nada aqui" +_timeIn: + seconds: "Em {n}s" + minutes: "Em {n}m" + hours: "Em {n}h" + days: "Em {n}d" + weeks: "Em {n} semanas" + months: "Em {n} meses" + years: "Em {n} anos" +_time: + second: "Segundo(s)" + minute: "Minuto(s)" + hour: "Hora(s)" + day: "Dia(s)" _2fa: + alreadyRegistered: "Você já cadastrou um dispositivo de autenticação de dois fatores." + registerTOTP: "Cadastrar aplicativo autenticador" + step1: "Inicialmente, instale um aplicativo autenticador (como {a} ou {b}) em seu dispositivo." + step2: "Então, escaneie o código QR exibido na tela." + step2Uri: "Acesse o seguinte URI se você estiver utilizando um aplicativo no computador" + step3Title: "Insira o código de autenticação" + step3: "Insira o código de autenticação (token) providenciado pelo seu aplicativo para terminar a configuração." + setupCompleted: "Configuração completa" + step4: "De agora em diante, quaisquer solicitações de entrada pedirão pelo código." + securityKeyNotSupported: "O seu navegador não é compatível com chaves de segurança." + registerTOTPBeforeKey: "Por favor, configure um aplicativo autenticador para registrar uma chave de segurança." securityKeyInfo: "Além da autenticação por impressão digital ou PIN, você também pode configurar a autenticação por chaves de segurança de hardware compatível com FIDO2 para proteger ainda mais a sua conta." + registerSecurityKey: "Registre um código de segurança" + securityKeyName: "Insira um nome para a chave" + tapSecurityKey: "Por favor, siga as instruções do navegador para registrar o código de segurança" + removeKey: "Remover código de segurança" removeKeyConfirm: "Deseja excluir {name}?" + whyTOTPOnlyRenew: "O autenticador não pode ser removido enquanto há códigos de segurança registrados." + renewTOTP: "Reconfigurar autenticador" + renewTOTPConfirm: "Isso interromperá o funcionamento dos códigos de aplicativos anteriores " + renewTOTPOk: "Reconfigurar" renewTOTPCancel: "Não, obrigado" + checkBackupCodesBeforeCloseThisWizard: "Antes de fechar essa janela, anote os códigos de backup a seguir." + backupCodes: "Códigos de backup" + backupCodesDescription: "Você pode utilizar esses códigos para ganhar acesso à conta caso sua autenticação de dois fatores esteja indisponível. Cada código pode ser utilizado apenas uma vez. Por favor, guarde-os em um local seguro." + backupCodeUsedWarning: "Um código de backup foi utilizado. Por favor, reconfigure a autenticação de dois fatores o quanto antes, caso não consiga utilizá-la." + backupCodesExhaustedWarning: "Todos os códigos de backup foram utilizados. Caso perca acesso à autenticação de dois fatores, você perderá o acesso à conta. Por favor, reconfigure a autenticação de dois fatores." + moreDetailedGuideHere: "Aqui está um guia detalhado" _permissions: "read:account": "Visualizar informações da conta" "write:account": "Editar informações da conta" @@ -1364,6 +2050,82 @@ _permissions: "write:gallery": "Editar sua galeria" "read:gallery-likes": "Visualizar a sua lista de curtidas da galeria" "write:gallery-likes": "Editar a sua lista de curtidas da galeria" + "read:flash": "Ver Play" + "write:flash": "Editar Plays" + "read:flash-likes": "Ver lista de Plays curtidas" + "write:flash-likes": "Editar lista de Plays curtidas" + "read:admin:abuse-user-reports": "Ver relatórios de usuário" + "write:admin:delete-account": "Excluir conta de usuário" + "write:admin:delete-all-files-of-a-user": "Excluir todos os arquivos de um usuário" + "read:admin:index-stats": "Ver estatísticas do índice do banco de dados" + "read:admin:table-stats": "Ver estatísticas da tabela do banco de dados" + "read:admin:user-ips": "Ver endereços IP do usuário" + "read:admin:meta": "Ver metadados da instância" + "write:admin:reset-password": "Mudar a senha do usuário" + "write:admin:resolve-abuse-user-report": "Resolver relatório de usuário" + "write:admin:send-email": "Enviar email" + "read:admin:server-info": "Ver informações do servidor" + "read:admin:show-moderation-log": "Ver log de moderação" + "read:admin:show-user": "Ver informações privadas do usuário" + "write:admin:suspend-user": "Suspender usuário" + "write:admin:unset-user-avatar": "Remover avatar do usuário" + "write:admin:unset-user-banner": "Remover banner do usuário" + "write:admin:unsuspend-user": "Cancelar a suspensão do usuário" + "write:admin:meta": "Gerenciar os metadados da instância" + "write:admin:user-note": "Gerenciar a nota de moderação" + "write:admin:roles": "Gerenciar cargos" + "read:admin:roles": "Ver cargos" + "write:admin:relays": "Gerenciar relays" + "read:admin:relays": "Ver relays" + "write:admin:invite-codes": "Gerenciar códigos de convite" + "read:admin:invite-codes": "Ver códigos de convite" + "write:admin:announcements": "Gerenciar anúncios" + "read:admin:announcements": "Ver anúncios" + "write:admin:avatar-decorations": "Gerenciar decorações de avatar" + "read:admin:avatar-decorations": "Ver decorações de avatar" + "write:admin:federation": "Gerenciar dados de federação" + "write:admin:account": "Gerenciar conta de usuário" + "read:admin:account": "Ver conta de usuário" + "write:admin:emoji": "Gerenciar emoji" + "read:admin:emoji": "Ver emoji" + "write:admin:queue": "Gerenciar trabalhos pendentes" + "read:admin:queue": "Ver informações de trabalhos pendentes" + "write:admin:promo": "Gerenciar notas de promoção" + "write:admin:drive": "Gerenciar Drive de usuário" + "read:admin:drive": "Ver informações de Drive de usuário" + "read:admin:stream": "Utilizar WebSocket API para Admin" + "write:admin:ad": "Gerenciar propagandas" + "read:admin:ad": "Ver propagandas" + "write:invite-codes": "Criar códigos de convite" + "read:invite-codes": "Obter códigos de convite" + "write:clip-favorite": "Gerenciar clipes favoritados" + "read:clip-favorite": "Ver Clipes favoritados" + "read:federation": "Ver dados de federação" + "write:report-abuse": "Reportar violação" +_auth: + shareAccessTitle: "Conceder permissões do aplicativo" + shareAccess: "Você gostaria de autorizar \"{name}\" para acessar essa conta?" + shareAccessAsk: "Você tem certeza de que gostaria de conceder ao aplicativo o acesso à conta?" + permission: "{name} solicita as seguintes permissões" + permissionAsk: "O aplicativo solicita as seguintes permissões" + pleaseGoBack: "Por favor, volte ao aplicativo" + callback: "Retornando ao aplicativo" + denied: "Acesso negado" + pleaseLogin: "Por favor, entre para autorizar aplicativos." +_antennaSources: + all: "Todas as notas" + homeTimeline: "Notas de usuários seguidos" + users: "Notas de usuários específicos" + userList: "Notas de uma lista específica de usuários" + userBlacklist: "Todas as notas, exceto as de um ou mais usuários específicos" +_weekday: + sunday: "Domingo" + monday: "Segunda-feira" + tuesday: "Terça-feira" + wednesday: "Quarta-feira" + thursday: "Quinta-feira" + friday: "Sexta-feira" + saturday: "Sábado" _widgets: profile: "Perfil" instanceInfo: "Informações da instância" @@ -1394,29 +2156,112 @@ _widgets: _userList: chooseList: "Selecione uma lista" clicker: "Clicker" + birthdayFollowings: "Usuários de aniversário hoje" _cw: + hide: "Esconder" show: "Carregar mais" + chars: "{count} caracteres" + files: "{count} arquivo(s)" _poll: + noOnlyOneChoice: "São necessárias, no mínimo, duas escolhas" + choiceN: "Escolha {n}" + noMore: "Você não pode adicionar mais escolhas" canMultipleVote: "Permitir múltipla seleção" + expiration: "Encerrar enquete" + infinite: "Nunca" + at: "Terminar em..." + after: "Terminar após..." + deadlineDate: "Data de término" + deadlineTime: "Tempo" + duration: "Duração" + votesCount: "{n} votos" + totalVotes: "{n} votos totais" vote: "Votar em enquetes" + showResult: "Ver resultados" + voted: "Votada" + closed: "Encerrada" + remainingDays: "{d} dia(s) {h} hora(s) restantes" + remainingHours: "{h} hora(s) {m} minuto(s) restantes" + remainingMinutes: "{m} minuto(s) {s} segundo(s) restantes" + remainingSeconds: "{s} segundo(s) restantes" _visibility: + public: "Público" + publicDescription: "Sua nota será visível para todos os usuários" home: "Início" + homeDescription: "Publicar apenas na linha do tempo Início" followers: "Seguidores" followersDescription: "Tornar visível apenas para os meus seguidores" + specified: "Mensagem Direta" + specifiedDescription: "Tornar visível apenas para usuários específicos" + disableFederation: "Defederar" + disableFederationDescription: "Não transmitir às outras instâncias" +_postForm: + replyPlaceholder: "Responder a essa nota..." + quotePlaceholder: "Citar essa nota..." + channelPlaceholder: "Postar em canal..." + _placeholders: + a: "Como vão as coisas?" + b: "O que está rolando por aí?" + c: "No que está pensando?" + d: "Do que você quer falar?" + e: "Comece a digitar..." + f: "Esperando você digitar..." _profile: name: "Nome" username: "Nome de usuário" + description: "Bio" + youCanIncludeHashtags: "Você pode incluir hashtags em sua bio." + metadata: "Informações Adicionais" + metadataEdit: "Editar informações adicionais" + metadataDescription: "Aqui, você pode exibir campos adicionais de informação no seu perfil." + metadataLabel: "Rótulo" + metadataContent: "Conteúdo" + changeAvatar: "Mudar avatar" + changeBanner: "Mudar banner" + verifiedLinkDescription: "Ao inserir um URL que contém um link para essa conta, um ícone de verificação será exibido ao lado do campo" + avatarDecorationMax: "Você pode adicionar até {max} decorações." _exportOrImport: + allNotes: "Todas as notas" favoritedNotes: "Notas nos favoritos" clips: "Clipe" followingList: "Seguindo" muteList: "Silenciar" blockingList: "Bloquear" userLists: "Listas" + excludeMutingUsers: "Excluir usuários silenciados" + excludeInactiveUsers: "Excluir usuários inativos" + withReplies: "Incluir respostas de usuários importados na linha do tempo" _charts: federation: "União" + apRequest: "Solicitações" + usersIncDec: "Diferença no número de usuários" + usersTotal: "Número total de usuários" + activeUsers: "Usuários ativos" + notesIncDec: "Diferença no número de notas" + localNotesIncDec: "Diferença no número de notas locais" + remoteNotesIncDec: "Diferença no número de notas remotas" + notesTotal: "Número total de notas" + filesIncDec: "Diferença no número de arquivos" + filesTotal: "Número total de arquivos" + storageUsageIncDec: "Diferença no uso de armazenamento" + storageUsageTotal: "Uso total de armazenamento" +_instanceCharts: + requests: "Solicitações" + users: "Diferença no número de usuários" + usersTotal: "Número cumulativo de usuários" + notes: "Diferença no número de notas" + notesTotal: "Número cumulativo de notas" + ff: "Diferença entre número de usuários seguidos/seguidores" + ffTotal: "Número cumulativo de usuários seguidos/seguidores" + cacheSize: "Diferença do tamanho do cache" + cacheSizeTotal: "Tamanho cumulativo do cache" + files: "Diferença no número de arquivos" + filesTotal: "Número cumulativo de arquivos" _timelines: home: "Início" + local: "Local" + social: "Social" + global: "Global" _play: new: "Criar Play" edit: "Editar Play" @@ -1425,18 +2270,66 @@ _play: deleted: "Play foi excluído" pageSetting: "Configurações do Play" editThisPage: "Editar este Play" + viewSource: "Ver fonte" my: "Meus Plays" liked: "Plays curtidos" + featured: "Popular" + title: "Título" script: "Script" summary: "Descrição" + visibilityDescription: "Pôr em privado significa que ele não será visível no perfil, mas qualquer um com o URL poderá acessar" _pages: + newPage: "Criar uma Página" + editPage: "Editar essa Página" + readPage: "Ver a fonte dessa Página" + created: "Página criada com sucesso" + updated: "Página atualizada com sucesso" deleted: "Página excluída com sucesso" + pageSetting: "Configurações da página" + nameAlreadyExists: "O URL de Página especificado já existe" + invalidNameTitle: "O URL de Página especificado é inválido" + invalidNameText: "Confira se o título da Página não está vazio" + editThisPage: "Editar essa Página" + viewSource: "Ver código-fonte" viewPage: "Visualizar as suas páginas" like: "Curtir" unlike: "Remover curtida" + my: "Minhas Páginas" liked: "Páginas curtidas" + featured: "Populares" + inspector: "Inspetor" + contents: "Conteúdo" + content: "Bloco da Página" + variables: "Variáveis" + title: "Título" + url: "URL da Página" + summary: "Resumo da página" + alignCenter: "Centralizar elementos" + hideTitleWhenPinned: "Esconder título da Página quando fixado em perfil" + font: "Fonte" + fontSerif: "Serif" + fontSansSerif: "Sans Serif" + eyeCatchingImageSet: "Escolher miniatura" + eyeCatchingImageRemove: "Excluir miniatura" + chooseBlock: "Adicionar bloco" + enterSectionTitle: "Insira um título à seção" + selectType: "Selecionar um tipo" + contentBlocks: "Conteúdo" + inputBlocks: "Inserir" + specialBlocks: "Especial" blocks: + text: "Texto" + textarea: "Área do texto" + section: "Seção" image: "imagem" + button: "Botão" + dynamic: "Blocos Dinâmicos" + dynamicDescription: "Esse bloco foi abolido. Por favor, use {play} de agora em diante." + note: "Nota embutida" + _note: + id: "ID da nota" + idDescription: "Você também pode colar o URL da nota aqui." + detailed: "Visão detalhada" _relayStatus: requesting: "Pendente" accepted: "Aprovado" @@ -1451,18 +2344,35 @@ _notification: youReceivedFollowRequest: "Você recebeu um pedido de seguidor" yourFollowRequestAccepted: "Seu pedido de seguidor foi aceito" pollEnded: "Os resultados da enquete agora estão disponíveis" + newNote: "Nova nota" + unreadAntennaNote: "Antena {name}" + roleAssigned: "Cargo dado" emptyPushNotificationMessage: "As notificações de alerta foram atualizadas" + achievementEarned: "Conquista desbloqueada" + testNotification: "Notificação teste" + checkNotificationBehavior: "Verificar aparência da notificação" + sendTestNotification: "Enviar notificação de teste" + notificationWillBeDisplayedLikeThis: "Notificações se parecem com isso" + reactedBySomeUsers: "{n} usuários reagiram" + likedBySomeUsers: "{n} usuários gostaram da nota" + renotedBySomeUsers: "{n} usuários repostaram a nota" + followedBySomeUsers: "{n} usuários te seguiram" + flushNotification: "Limpar notificações" _types: all: "Todas" + note: "Novas notas" follow: "Seguindo" mention: "Menção" reply: "Respostas" renote: "Repostar" - quote: "Citar" + quote: "Citações" reaction: "Reações" pollEnded: "Enquetes terminando" receiveFollowRequest: "Recebeu pedidos de seguidor" followRequestAccepted: "Aceitou pedidos de seguidor" + roleAssigned: "Cargo dado" + achievementEarned: "Conquista desbloqueada" + login: "Iniciar sessão" app: "Notificações de aplicativos conectados" _actions: followBack: "te seguiu de volta" @@ -1472,13 +2382,23 @@ _deck: alwaysShowMainColumn: "Sempre mostrar a coluna principal" columnAlign: "Alinhar colunas" addColumn: "Adicionar coluna" + newNoteNotificationSettings: "Opções de notificação para novas notas" + configureColumn: "Configurar coluna" swapLeft: "Trocar de posição com a coluna à esquerda" swapRight: "Trocar de posição com a coluna à direita" swapUp: "Trocar de posição com a coluna acima" swapDown: "Trocar de posição com a coluna abaixo" + stackLeft: "Empilhar na coluna à esquerda" popRight: "Acoplar coluna à direita" profile: "Perfil" + newProfile: "Novo perfil" deleteProfile: "Remover perfil" + introduction: "Crie a interface perfeita para você arranjando as colunas livremente!" + introduction2: "Clique no + à direita da tela para adicionar novas colunas quando quiser." + widgetsIntroduction: "Por favor, selecione \"Editar widgets\" no menu em coluna e adicione um widget." + useSimpleUiForNonRootPages: "Usar UI simples para páginas navegadas" + usedAsMinWidthWhenFlexible: "A largura mínima será usada para isso quando o \"Ajuste automático da largura\" estiver ativado" + flexible: "Ajuste automático da largura" _columns: main: "Principal" widgets: "Widgets" @@ -1490,18 +2410,230 @@ _deck: mentions: "Menções" direct: "Notas diretas" roleTimeline: "Linha do tempo do cargo" +_dialog: + charactersExceeded: "Você excedeu o limite de caracteres! Atualmente em {current} de {max}." + charactersBelow: "Você está abaixo do limite mínimo de caracteres! Atualmente em {current} of {min}." +_disabledTimeline: + title: "Linha do tempo desabilitada" + description: "Você não pode acessar essa linha do tempo sob o seu cargo atual." _drivecleaner: orderBySizeDesc: "Tamanho descendente" orderByCreatedAtAsc: "Data ascendente" _webhookSettings: + createWebhook: "Criar Webhook" + modifyWebhook: "Modificar Webhook" name: "Nome" + secret: "Segredo" + trigger: "Gatilho" active: "Ativado" _events: follow: "Quando seguindo um usuário" followed: "Quando sendo seguido" + note: "Ao postar uma nota" + reply: "Quando receber uma resposta" renote: "Quando repostado" + reaction: "Quando receber uma reação" + mention: "Quando for mencionado" + _systemEvents: + abuseReport: "Quando receber um relatório de abuso" + abuseReportResolved: "Quando relatórios de abuso forem resolvidos " + userCreated: "Quando um usuário é criado" + deleteConfirm: "Você tem certeza de que deseja excluir o Webhook?" +_abuseReport: + _notificationRecipient: + createRecipient: "Adicionar destinatário para relatórios de abuso" + modifyRecipient: "Editar destinatários para relatórios de abuso" + recipientType: "TIpo de notificação" + _recipientType: + mail: "E-mail" + webhook: "Webhook" + _captions: + mail: "Enviar o email aos endereços dos moderadores ao receber relatório de abuso." + webhook: "Enviar uma notificação ao SystemWebhook quando você receber um resolver um relatório de abuso." + keywords: "Palavras-chave" + notifiedUser: "Usuários para notificar" + notifiedWebhook: "Webhook usado" + deleteConfirm: "Você tem certeza de que quer excluir o destinatário da notificação?" _moderationLogTypes: + createRole: "Cargo criado" + deleteRole: "Cargo excluído" + updateRole: "Cargo atualizado" + assignRole: "Cargo atribuído" + unassignRole: "Cargo removido" suspend: "Suspender" + unsuspend: "Suspensão cancelada" + addCustomEmoji: "Emoji personalizado adicionado" + updateCustomEmoji: "Emoji personalizado atualizado" + deleteCustomEmoji: "Emoji personalizado removido" + updateServerSettings: "Configurações de servidor atualizadas" + updateUserNote: "Nota de moderação atualizada" + deleteDriveFile: "Arquivo excluído" + deleteNote: "Nota excluída" + createGlobalAnnouncement: "Anúncio global criado" + createUserAnnouncement: "Anúncio de usuário criado" + updateGlobalAnnouncement: "Anúncio global atualizado" + updateUserAnnouncement: "Anúncio de usuário atualizado" + deleteGlobalAnnouncement: "Anúncio global excluído" + deleteUserAnnouncement: "Anúncio de usuário excluído" resetPassword: "Redefinir senha" + suspendRemoteInstance: "Instância remota suspensa" + unsuspendRemoteInstance: "Suspensão de instância remota removida" + updateRemoteInstanceNote: "Nota de moderação atualizada para instância remota." + markSensitiveDriveFile: "Arquivo marcado como sensível" + unmarkSensitiveDriveFile: "Arquivo desmarcado como sensível" + resolveAbuseReport: "Relatório resolvido" + createInvitation: "Convite gerado" + createAd: "Propaganda criada" + deleteAd: "Propaganda excluída" + updateAd: "Propaganda atualizada" + createAvatarDecoration: "Decoração de avatar criada" + updateAvatarDecoration: "Decoração de avatar atualizada" + deleteAvatarDecoration: "Decoração de avatar removida" + unsetUserAvatar: "Remover avatar de usuário" + unsetUserBanner: "Remover banner de usuário" + createSystemWebhook: "Criar SystemWebhook" + updateSystemWebhook: "Atualizar SystemWebhook" + deleteSystemWebhook: "Remover SystemWebhook" + createAbuseReportNotificationRecipient: "Criar um destinatário para relatórios de abuso" + updateAbuseReportNotificationRecipient: "Atualizar destinatários para relatórios de abuso" + deleteAbuseReportNotificationRecipient: "Remover um destinatário para relatórios de abuso" + deleteAccount: "Remover conta" + deletePage: "Remover página" + deleteFlash: "Remover Play" + deleteGalleryPost: "Remover a publicação da galeria" +_fileViewer: + title: "Detalhes do arquivo" + type: "Tipo de arquivo" + size: "Tamanho do arquivo" + url: "URL" + uploadedAt: "Adicionado em" + attachedNotes: "Notas anexadas" + thisPageCanBeSeenFromTheAuthor: "Essa página só pode ser vista pelo usuário que enviou esse arquivo." +_externalResourceInstaller: + title: "Instalar de site externo" + checkVendorBeforeInstall: "Tenha certeza de que o distribuidor desse recurso é confiável antes da instalação." + _plugin: + title: "Deseja instalar esse plugin?" + metaTitle: "Informações do plugin" + _theme: + title: "Deseja instalar esse tema?" + metaTitle: "Informações do tema" + _meta: + base: "Paleta de cores base" + _vendorInfo: + title: "Informações do distribuidor" + endpoint: "Endpoint referenciado" + hashVerify: "Verificação de hashes" + _errors: + _invalidParams: + title: "Parâmetros inválidos" + description: "Não há informações suficientes para carregar dados do site externo. Por favor, confirme o URL inserido." + _resourceTypeNotSupported: + title: "Esse recurso externo é incompatível" + description: "Esse tipo de recuso externo é incompatível. Por favor, comunique o administrador do site." + _failedToFetch: + title: "Não foi possível obter dados" + fetchErrorDescription: "Houve um erro ao comunicar com o site externo. Se tentar novamente não resolver o problema, contate o administrador do site." + parseErrorDescription: "Houve um erro processando os dados do site externo. Por favor, contate o administrador do site." + _hashUnmatched: + title: "Verificação de dados falhou" + description: "Houve um erro verificando a integridade do conteúdo obtido. Como medida de segurança, a instalação foi interrompida. Por favor, contate o administrador do site." + _pluginParseFailed: + title: "Erro AiScript" + description: "Os dados solicitados foram obtidos com sucesso, mas houve um erro na leitura do AiScript. Por favor, contate o autor do plugin. Detalhes de erro podem ser vistos no console Javascript." + _pluginInstallFailed: + title: "A instalação do plugin falhou." + description: "Houve um problema na instalação do plugin. Por favor, tente novamente. Detalhes de erro podem ser vistos no console Javascript." + _themeParseFailed: + title: "Erro na leitura do tema" + description: "Os dados solicitados foram obtidos com sucesso, mas houve um erro na leitura do tema. Por favor, contate o autor do tema. Detalhes de erro podem ser vistos no console Javascript." + _themeInstallFailed: + title: "Falha ao instalar tema" + description: "Houve um problema na instalação do tema. Por favor, tente novamente. Detalhes do erro podem ser vistos no console Javascript." +_dataSaver: + _media: + title: "Carregando mídia" + description: "Previne que mídia seja carregada automaticamente. Mídias escondidas serão carregadas quando selecionadas." + _avatar: + title: "Imagem do avatar" + description: "Parar animação de avatares. Imagens animadas podem ter um arquivo mais pesado do que imagens normais, potencialmente levando a reduções no tráfego de dados." + _urlPreview: + title: "Miniaturas na prévia de URLs" + description: "Miniaturas na prévia de URLs não serão mais carregadas." + _code: + title: "Destaque de código" + description: "Se as notações de formatação de código forem utilizadas em MFM, elas não irão carregar até serem selecionadas. Destaque de código exige baixar arquivos de alta definição para cada linguagem de programação. Logo, desabilitar o carregamento automático desses arquivos diminui a quantidade de informação comunicada." +_hemisphere: + N: "Hemisfério Norte" + S: "Hemisfério Sul" + caption: "Utilizado em algumas configurações de aplicativo para determinar a estação do ano." _reversi: + reversi: "Reversi" + gameSettings: "Configurações de jogo" + chooseBoard: "Escolha um tabuleiro" + blackOrWhite: "Preto/Branco" + blackIs: "{name} é as peças Pretas" + rules: "Regras" + thisGameIsStartedSoon: "O jogo começará em breve" + waitingForOther: "Esperando o turno do oponente" + waitingForMe: "Esperando o seu turno" + waitingBoth: "Prepare-se" + ready: "Pronto" + cancelReady: "Não pronto" + opponentTurn: "Turno do oponente" + myTurn: "Seu turno" + turnOf: "É o turno de {name}" + pastTurnOf: "Turno de {name}" + surrender: "Desistir" + surrendered: "Desistiu" + timeout: "Fim do tempo" + drawn: "Empate" + won: "{name} venceu" + black: "Preto" + white: "Branco" total: "Total" + turnCount: "Turno {count}" + myGames: "Meus jogos" + allGames: "Todos os jogos" + ended: "Terminado" + playing: "Atualmente jogando" + isLlotheo: "Aquele com menos pedras vence (Llotheo)" + loopedMap: "Mapa em ‘loop’" + canPutEverywhere: "É possível pôr em qualquer lugar" + timeLimitForEachTurn: "Tempo limite por turno" + freeMatch: "Partida Livre" + lookingForPlayer: "À procura de adversários..." + gameCanceled: "A partida foi cancelada." + shareToTlTheGameWhenStart: "Compartilhar jogo na linha do tempo ao iniciar" + iStartedAGame: "O jogo começou! #MisskeyReversi" + opponentHasSettingsChanged: "O oponente alterou as configurações dele" + allowIrregularRules: "Regras irregulares (completamente livre)" + disallowIrregularRules: "Sem regras irregulares" + showBoardLabels: "Exibir numeração de linha e coluna no tabuleiro" + useAvatarAsStone: "Utilizar avatares de usuário como as pedras" +_offlineScreen: + title: "Offline - não foi possível conectar ao servidor" + header: "Não foi possível conectar ao servidor" +_urlPreviewSetting: + title: "Configurações da prévia de URL" + enable: "Habilitar prévia de URL" + timeout: "Tempo máximo para obter a prévia (ms)" + timeoutDescription: "Se demorar mais que esse valor para obter uma prévia, ela não será gerada." + maximumContentLength: "Content-Length máximo (em bytes)" + maximumContentLengthDescription: "Se o Content-Length for maior que esse valor, a prévia não será gerada." + requireContentLength: "Gerar previu apenas se houver cabeçalho Content-Length disponível na solicitação" + requireContentLengthDescription: "Se o outro servidor não retornar um cabeçalho Content-Length, a prévia não será gerada." + userAgent: "User-Agent" + userAgentDescription: "Define o User-Agent a ser usado ao gerar prévias. Se for deixado em branco, será usado o User-Agent padrão." + summaryProxy: "Endpoints do Proxy que geram prévias" + summaryProxyDescription: "Fora do Misskey, gerar prévias usando o Sumally Proxy." + summaryProxyDescription2: "Os parâmetros a seguir são vinculados ao proxy como um 'query string'. Se o proxy não os suportar, os valores serão ignorados." +_mediaControls: + pip: "Picture-in-Picture" + playbackRate: "Velocidade de Reprodução" + loop: "Reprodução em Loop" +_contextMenu: + title: "Menu de contexto" + app: "Aplicativo" + appWithShift: "Aplicativo com a tecla shift" + native: "Nativo" diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index 328d34405e..3cc09aa5c2 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -453,7 +453,6 @@ or: "Sau" language: "Limbă" uiLanguage: "Limba interfeței" aboutX: "Despre {x}" -disableDrawer: "Nu folosi meniuri în stil sertar" noHistory: "Nu există istoric" signinHistory: "Istoric autentificări" doing: "Se procesează..." @@ -626,10 +625,7 @@ abuseReported: "Raportul tău a fost trimis. Mulțumim." reporter: "Raportorul" reporteeOrigin: "Originea raportatului" reporterOrigin: "Originea raportorului" -forwardReport: "Redirecționează raportul către instanța externă" -forwardReportIsAnonymous: "În locul contului tău, va fi afișat un cont anonim, de sistem, ca raportor către instanța externă." send: "Trimite" -abuseMarkAsResolved: "Marchează raportul ca rezolvat" openInNewTab: "Deschide în tab nou" openInSideView: "Deschide în vedere laterală" defaultNavigationBehaviour: "Comportament de navigare implicit" @@ -715,6 +711,7 @@ _notification: renote: "Re-notează" quote: "Citează" reaction: "Reacție" + login: "Autentifică-te" _actions: reply: "Răspunde" renote: "Re-notează" @@ -728,6 +725,10 @@ _deck: mentions: "Mențiuni" _webhookSettings: name: "Nume" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: suspend: "Suspendă" resetPassword: "Resetează parola" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 71f5cad601..70178ec2fd 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -2,7 +2,7 @@ _lang_: "Русский" headlineMisskey: "Сеть, сплетённая из заметок" introMisskey: "Добро пожаловать! Misskey — это децентрализованный сервис микроблогов с открытым исходным кодом.\nПишите «заметки» — делитесь со всеми происходящим вокруг или рассказывайте о себе 📡\nСтавьте «реакции» — выражайте свои чувства и эмоции от заметок других 👍\nОткройте для себя новый мир 🚀" -poweredByMisskeyDescription: "{name} – сервис на платформе с открытым исходным кодом Misskey, называемый инстансом Misskey." +poweredByMisskeyDescription: "{name} – сервис на платформе с открытым исходным кодом Misskey, называемый экземпляром Misskey." monthAndDay: "{day}.{month}" search: "Поиск" notifications: "Уведомления" @@ -10,15 +10,15 @@ username: "Имя пользователя" password: "Пароль" forgotPassword: "Забыли пароль?" fetchingAsApObject: "Приём с других сайтов" -ok: "Окей" +ok: "Подтвердить" gotIt: "Ясно!" cancel: "Отмена" noThankYou: "Нет, спасибо" enterUsername: "Введите имя пользователя" -renotedBy: "{user} делится" +renotedBy: "{user} репостнул(а)" noNotes: "Нет ни одной заметки" noNotifications: "Нет уведомлений" -instance: "Инстанс" +instance: "Экземпляр" settings: "Настройки" notificationSettings: "Настройки уведомлений" basicSettings: "Основные настройки" @@ -45,22 +45,24 @@ pin: "Закрепить в профиле" unpin: "Открепить от профиля" copyContent: "Скопировать содержимое" copyLink: "Скопировать ссылку" +copyLinkRenote: "Скопировать ссылку на репост" delete: "Удалить" deleteAndEdit: "Удалить и отредактировать" -deleteAndEditConfirm: "Удалить эту заметку и создать отредактированную? Все реакции, ссылки и ответы на существующую будут будут потеряны." +deleteAndEditConfirm: "Удалить этот пост и отредактировать заново? Все реакции, репосты и ответы на него также будут удалены." addToList: "Добавить в список" addToAntenna: "Добавить к антенне" sendMessage: "Отправить сообщение" copyRSS: "Скопировать RSS" copyUsername: "Скопировать имя пользователя" -copyUserId: "Скопировать идентификатор пользователя" -copyNoteId: "Скопировать идентификатор заметки" +copyUserId: "Скопировать ID пользователя" +copyNoteId: "Скопировать ID поста" copyFileId: "Скопировать ID файла" copyFolderId: "Скопировать ID папки" -copyProfileUrl: "Скопировать URL профиля " +copyProfileUrl: "Скопировать ссылку на профиль" searchUser: "Поиск людей" +searchThisUsersNotes: "Искать по заметкам пользователя" reply: "Ответ" -loadMore: "Показать еще" +loadMore: "Загрузить ещё" showMore: "Показать ещё" showLess: "Закрыть" youGotNewFollower: "Новый подписчик" @@ -107,11 +109,14 @@ enterEmoji: "Введите эмодзи" renote: "Репост" unrenote: "Отмена репоста" renoted: "Репост совершён." +renotedToX: "Репостнуть в {name}." cantRenote: "Это нельзя репостить." cantReRenote: "Невозможно репостить репост." quote: "Цитата" inChannelRenote: "В канале" inChannelQuote: "Заметки в канале" +renoteToChannel: "Репостнуть в канал" +renoteToOtherChannel: "Репостнуть в другой канал" pinnedNote: "Закреплённая заметка" pinned: "Закрепить в профиле" you: "Вы" @@ -150,6 +155,7 @@ editList: "Редактировать список" selectChannel: "Выберите канал" selectAntenna: "Выберите антенну" editAntenna: "Редактировать антенну" +createAntenna: "Создать антенну" selectWidget: "Выберите виджет" editWidgets: "Редактировать виджеты" editWidgetsExit: "Готово" @@ -157,11 +163,12 @@ customEmojis: "Собственные эмодзи" emoji: "Эмодзи" emojis: "Эмодзи" emojiName: "Название эмодзи" -emojiUrl: "URL эмодзи" +emojiUrl: "Ссылка на эмодзи" addEmoji: "Добавить эмодзи" settingGuide: "Рекомендуемые настройки" cacheRemoteFiles: "Кешировать внешние файлы" cacheRemoteFilesDescription: "Когда эта настройка отключена, файлы с других сайтов будут загружаться прямо оттуда. Это сэкономит место на сервере, но увеличит трафик, так как не будут создаваться эскизы." +youCanCleanRemoteFilesCache: "Вы можете очистить кэш, нажав на кнопку 🗑️ в меню управления файлами." cacheRemoteSensitiveFiles: "Кэшировать внешние файлы «не для всех»" cacheRemoteSensitiveFilesDescription: "Если отключено, файлы «не для всех» загружаются непосредственно с удалённых серверов, не кэшируясь." flagAsBot: "Аккаунт бота" @@ -175,6 +182,10 @@ addAccount: "Добавить учётную запись" reloadAccountsList: "Обновить список учётных записей" loginFailed: "Неудачная попытка входа" showOnRemote: "Перейти к оригиналу на сайт" +continueOnRemote: "Продолжить на удалённом сервере" +chooseServerOnMisskeyHub: "Выбрать сервер с Misskey Hub" +specifyServerHost: "Укажите сервер напрямую" +inputHostName: "Введите домен" general: "Общее" wallpaper: "Обои" setWallpaper: "Установить обои" @@ -185,6 +196,7 @@ followConfirm: "Подписаться на {name}?" proxyAccount: "Учётная запись прокси" proxyAccountDescription: "Учетная запись прокси предназначена служить подписчиком на пользователей с других сайтов. Например, если пользователь добавит кого-то с другого сайта а список, деятельность того не отобразится, пока никто с этого же сайта не подписан на него. Чтобы это стало возможным, на него подписывается прокси." host: "Хост" +selectSelf: "Выбрать себя" selectUser: "Выберите пользователя" recipient: "Кому" annotation: "Описание" @@ -199,6 +211,7 @@ perHour: "По часам" perDay: "По дням" stopActivityDelivery: "Остановить отправку обновлений активности" blockThisInstance: "Блокировать этот инстанс" +silenceThisInstance: "Заглушить этот инстанс" operations: "Операции" software: "Программы" version: "Версия" @@ -218,6 +231,7 @@ clearCachedFiles: "Очистить кэш" clearCachedFilesConfirm: "Удалить все закэшированные файлы с других сайтов?" blockedInstances: "Заблокированные инстансы" blockedInstancesDescription: "Введите список инстансов, которые хотите заблокировать. Они больше не смогут обмениваться с вашим инстансом." +silencedInstances: "Заглушённые инстансы" muteAndBlock: "Скрытие и блокировка" mutedUsers: "Скрытые пользователи" blockedUsers: "Заблокированные пользователи" @@ -236,7 +250,7 @@ noJobs: "Нет заданий" federating: "Федерируется" blocked: "Заблокировано" suspended: "Заморожено" -all: "Всё" +all: "Все" subscribing: "Подписка" publishing: "Публикация" notResponding: "Нет ответа" @@ -268,7 +282,7 @@ messaging: "Сообщения" upload: "Загрузить" keepOriginalUploading: "Сохранить исходное изображение" keepOriginalUploadingDescription: "Сохраняет исходную версию при загрузке изображений. Если выключить, то при загрузке браузер генерирует изображение для публикации." -fromDrive: "С «диска»" +fromDrive: "С Диска" fromUrl: "По ссылке" uploadFromUrl: "Загрузить по ссылке" uploadFromUrlDescription: "Ссылка на файл, который хотите загрузить" @@ -308,6 +322,7 @@ selectFile: "Выберите файл" selectFiles: "Выберите файлы" selectFolder: "Выберите папку" selectFolders: "Выберите папки" +fileNotSelected: "Файл не выбран" renameFile: "Переименовать файл" folderName: "Имя папки" createFolder: "Создать папку" @@ -359,8 +374,8 @@ disablingTimelinesInfo: "У администраторов и модератор registration: "Регистрация" enableRegistration: "Разрешить регистрацию" invite: "Пригласить" -driveCapacityPerLocalAccount: "Объём диска на одного локального пользователя" -driveCapacityPerRemoteAccount: "Объём диска на одного пользователя с другого сайта" +driveCapacityPerLocalAccount: "Объём Диска на одного локального пользователя" +driveCapacityPerRemoteAccount: "Объём Диска на одного пользователя с другого экземпляра" inMb: "В мегабайтах" bannerUrl: "Ссылка на изображение в шапке" backgroundImageUrl: "Ссылка на фоновое изображение" @@ -379,6 +394,7 @@ mcaptcha: "mCaptcha" enableMcaptcha: "Включить mCaptcha" mcaptchaSiteKey: "Ключ сайта" mcaptchaSecretKey: "Секретный ключ" +mcaptchaInstanceUrl: "Ссылка на сервер mCaptcha" recaptcha: "reCAPTCHA" enableRecaptcha: "Включить reCAPTCHA" recaptchaSiteKey: "Ключ сайта" @@ -393,7 +409,8 @@ manageAntennas: "Настройки антенн" name: "Название" antennaSource: "Источник антенны" antennaKeywords: "Ключевые слова" -antennaExcludeKeywords: "Исключения" +antennaExcludeKeywords: "Чёрный список слов" +antennaExcludeBots: "Исключать ботов" antennaKeywordsDescription: "Пишите слова через пробел в одной строке, чтобы ловить их появление вместе; на отдельных строках располагайте слова, или группы слов, чтобы ловить любые из них." notifyAntenna: "Уведомлять о новых заметках" withFileAntenna: "Только заметки с вложениями" @@ -426,6 +443,7 @@ totp: "Приложение-аутентификатор" totpDescription: "Описание приложения-аутентификатора" moderator: "Модератор" moderation: "Модерация" +moderationLogs: "Журнал модерации" nUsersMentioned: "Упомянуло пользователей: {n}" securityKeyAndPasskey: "Ключ безопасности и парольная фраза" securityKey: "Ключ безопасности" @@ -458,10 +476,12 @@ retype: "Введите ещё раз" noteOf: "Что пишет {user}" quoteAttached: "Цитата" quoteQuestion: "Хотите добавить цитату?" +attachAsFileQuestion: "Текста в буфере обмена слишком много. Прикрепить как текстовый файл?" noMessagesYet: "Пока ни одного сообщения" newMessageExists: "Новое сообщение" onlyOneFileCanBeAttached: "К сообщению можно прикрепить только один файл" signinRequired: "Пожалуйста, войдите" +signinOrContinueOnRemote: "Чтобы продолжить, вам необходимо войти в аккаунт на своём сервере или зарегистрироваться / войти в аккаунт на этом." invitations: "Приглашения" invitationCode: "Код приглашения" checking: "Проверка" @@ -471,7 +491,7 @@ usernameInvalidFormat: "Можно использовать только лат tooShort: "Слишком короткий" tooLong: "Слишком длинный" weakPassword: "Слабый пароль" -normalPassword: "Годный пароль" +normalPassword: "Хороший пароль" strongPassword: "Надёжный пароль" passwordMatched: "Совпали" passwordNotMatched: "Не совпадают" @@ -483,8 +503,8 @@ uiLanguage: "Язык интерфейса" aboutX: "Описание {x}" emojiStyle: "Стиль эмодзи" native: "Системные" -disableDrawer: "Не использовать выдвижные меню" showNoteActionsOnlyHover: "Показывать кнопки у заметок только при наведении" +showReactionsCount: "Видеть количество реакций на заметках" noHistory: "История пока пуста" signinHistory: "Журнал посещений" enableAdvancedMfm: "Включить расширенный MFM" @@ -547,7 +567,7 @@ popout: "Развернуть" volume: "Громкость" masterVolume: "Основная регулировка громкости" notUseSound: "Выключить звук" -useSoundOnlyWhenActive: "Использовать звук, когда Misskey активен." +useSoundOnlyWhenActive: "Воспроизводить звук только когда Misskey активен." details: "Подробнее" chooseEmoji: "Выберите эмодзи" unableToProcess: "Не удаётся завершить операцию" @@ -601,7 +621,7 @@ poll: "Опрос" useCw: "Скрывать содержимое под предупреждением" enablePlayer: "Включить проигрыватель" disablePlayer: "Выключить проигрыватель" -expandTweet: "Развернуть твит" +expandTweet: "Развернуть заметку" themeEditor: "Редактор темы оформления" description: "Описание" describeFile: "Добавить подпись" @@ -613,7 +633,7 @@ plugins: "Расширения" preferencesBackups: "Резервная копия" deck: "Пульт" undeck: "Покинуть пульт" -useBlurEffectForModal: "Размывка под формой поверх всего" +useBlurEffectForModal: "Размытие за формой ввода заметки" useFullReactionPicker: "Полнофункциональный выбор реакций" width: "Ширина" height: "Высота" @@ -644,7 +664,7 @@ smtpSecure: "Использовать SSL/TLS для SMTP-соединений" smtpSecureInfo: "Выключите при использовании STARTTLS." testEmail: "Проверка доставки электронной почты" wordMute: "Скрытие слов" -hardWordMute: "" +hardWordMute: "Строгое скрытие слов" regexpError: "Ошибка в регулярном выражении" regexpErrorDescription: "В списке {tab} скрытых слов, в строке {line} обнаружена синтаксическая ошибка:" instanceMute: "Глушение инстансов" @@ -680,10 +700,7 @@ abuseReported: "Жалоба отправлена. Большое спасибо reporter: "Сообщивший" reporteeOrigin: "О ком сообщено" reporterOrigin: "Кто сообщил" -forwardReport: "Отправить жалобу на инстанс автора." -forwardReportIsAnonymous: "Жалоба на удалённый инстанс будет отправлена анонимно. Вместо ваших данных у получателя будет отображена системная учётная запись." send: "Отправить" -abuseMarkAsResolved: "Отметить жалобу как решённую" openInNewTab: "Открыть в новой вкладке" openInSideView: "Открывать в боковой колонке" defaultNavigationBehaviour: "Поведение навигации по умолчанию" @@ -726,6 +743,7 @@ lockedAccountInfo: "Даже если вы вручную подтверждае alwaysMarkSensitive: "Отмечать файлы как «содержимое не для всех» по умолчанию" loadRawImages: "Сразу показывать изображения в полном размере" disableShowingAnimatedImages: "Не проигрывать анимацию" +highlightSensitiveMedia: "Выделять содержимое не для всех" verificationEmailSent: "Вам отправлено письмо для подтверждения. Пройдите, пожалуйста, по ссылке из письма, чтобы завершить проверку." notSet: "Не настроено" emailVerified: "Адрес электронной почты подтверждён." @@ -743,7 +761,7 @@ makeExplorable: "Опубликовать профиль в «Обзоре»." makeExplorableDescription: "Если выключить, ваш профиль не будет показан в разделе «Обзор»." showGapBetweenNotesInTimeline: "Показывать разделитель между заметками в ленте" duplicate: "Дубликат" -left: "Влево" +left: "Слева" center: "По центру" wide: "Толстый" narrow: "Тонкий" @@ -822,7 +840,7 @@ noMaintainerInformationWarning: "Не заполнены сведения об noBotProtectionWarning: "Ботозащита не настроена" configure: "Настроить" postToGallery: "Опубликовать в галерею" -postToHashtag: "Написать заметку с этим хэштегом" +postToHashtag: "Написать заметку с этим хештегом" gallery: "Галерея" recentPosts: "Недавние публикации" popularPosts: "Популярные публикации" @@ -839,13 +857,13 @@ emailNotConfiguredWarning: "Не указан адрес электронной ratio: "Соотношение" previewNoteText: "Предварительный просмотр" customCss: "Индивидуальный CSS" -customCssWarn: "Используйте эту настройку только если знаете, что делаете. Ошибки здесь чреваты тем, что сайт перестанет нормально работать у вас." +customCssWarn: "Используйте эту настройку только если знаете, что делаете. Ошибки здесь чреваты тем, что у вас перестанет нормально работать сайт." global: "Всеобщая" squareAvatars: "Квадратные аватарки" sent: "Отправить" received: "Получено" searchResult: "Результаты поиска" -hashtags: "Хэштег" +hashtags: "Хештеги" troubleshooting: "Разрешение проблем" useBlurEffect: "Размытие в интерфейсе" learnMore: "Подробнее" @@ -857,7 +875,7 @@ accountDeletionInProgress: "В настоящее время выполняет usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже." aiChanMode: "Режим Ай" devMode: "Режим разработчика" -keepCw: "Сохраняйте Предупреждения о содержимом" +keepCw: "Сохраняйте предупреждения о содержимом" pubSub: "Учётные записи Pub/Sub" lastCommunication: "Последнее сообщение" resolved: "Решено" @@ -878,6 +896,8 @@ makeReactionsPublicDescription: "Список сделанных вами реа classic: "Классика" muteThread: "Скрыть цепочку" unmuteThread: "Отменить сокрытие цепочки" +followingVisibility: "Видимость подписок" +followersVisibility: "Видимость подписчиков" continueThread: "Показать следующие ответы" deleteAccountConfirm: "Учётная запись будет безвозвратно удалена. Подтверждаете?" incorrectPassword: "Пароль неверен." @@ -987,6 +1007,7 @@ assign: "Назначить" unassign: "Отменить назначение" color: "Цвет" manageCustomEmojis: "Управлять пользовательскими эмодзи" +manageAvatarDecorations: "Управление украшениями аватара" youCannotCreateAnymore: "Вы достигли лимита создания." cannotPerformTemporary: "Временно недоступен" cannotPerformTemporaryDescription: "Это действие временно невозможно выполнить из-за превышения лимита выполнения." @@ -1003,7 +1024,8 @@ thisPostMayBeAnnoying: "Это сообщение может быть непри thisPostMayBeAnnoyingHome: "Этот пост может быть отправлен на главную" thisPostMayBeAnnoyingCancel: "Этот пост не может быть отменен." thisPostMayBeAnnoyingIgnore: "Этот пост может быть проигнорирован " -collapseRenotes: "Свернуть репосты" +collapseRenotes: "Сворачивать увиденные репосты" +collapseRenotesDescription: "Сворачивать посты с которыми вы взаимодействовали." internalServerError: "Внутренняя ошибка сервера" internalServerErrorDescription: "Внутри сервера произошла непредвиденная ошибка." copyErrorInfo: "Скопировать код ошибки" @@ -1027,7 +1049,10 @@ resetPasswordConfirm: "Сбросить пароль?" sensitiveWords: "Чувствительные слова" sensitiveWordsDescription: "Установите общедоступный диапазон заметки, содержащей заданное слово, на домашний. Можно сделать несколько настроек, разделив их переносами строк." sensitiveWordsDescription2: "Разделение пробелом создаёт спецификацию AND, а разделение косой чертой создаёт регулярное выражение." +prohibitedWords: "Запрещённые слова" +prohibitedWordsDescription: "Включает вывод ошибки при попытке опубликовать пост, содержащий указанное слово/набор слов.\nМножество слов может быть указано, разделяемые новой строкой." prohibitedWordsDescription2: "Разделение пробелом создаёт спецификацию AND, а разделение косой чертой создаёт регулярное выражение." +hiddenTags: "Скрытые хештеги" notesSearchNotAvailable: "Поиск заметок недоступен" license: "Лицензия" unfavoriteConfirm: "Удалить избранное?" @@ -1038,9 +1063,14 @@ retryAllQueuesConfirmTitle: "Хотите попробовать ещё раз?" retryAllQueuesConfirmText: "Нагрузка на сервер может увеличиться" enableChartsForRemoteUser: "Создание диаграмм для удалённых пользователей" enableChartsForFederatedInstances: "Создание диаграмм для удалённых серверов" +showClipButtonInNoteFooter: "Показать кнопку добавления в подборку в меню действий с заметкой" +reactionsDisplaySize: "Размер реакций" +limitWidthOfReaction: "Ограничить максимальную ширину реакций и отображать их в уменьшенном размере." noteIdOrUrl: "ID или ссылка на заметку" video: "Видео" videos: "Видео" +audio: "Звук" +audioFiles: "Звуковые файлы" dataSaver: "Экономия трафика" accountMigration: "Перенос учётной записи" accountMoved: "Учётная запись перенесена" @@ -1052,12 +1082,13 @@ editMemo: "Изменить памятку" reactionsList: "Список реакций" renotesList: "Репосты" notificationDisplay: "Отображение уведомлений" -leftTop: "Влево вверх" -rightTop: "Вправо вверх" -leftBottom: "Влево вниз" -rightBottom: "Вправо вниз" -vertical: "Вертикальная" -horizontal: "Сбоку" +leftTop: "Слева вверху" +rightTop: "Справа сверху" +leftBottom: "Слева внизу" +rightBottom: "Справа внизу" +stackAxis: "Положение уведомлений" +vertical: "Вертикально" +horizontal: "Горизонтально" position: "Позиция" serverRules: "Правила сервера" pleaseConfirmBelowBeforeSignup: "Для регистрации на данном сервере, необходимо согласится с нижеследующими положениями." @@ -1069,57 +1100,114 @@ createNoteFromTheFile: "Создать заметку из этого файла archive: "Архив" channelArchiveConfirmTitle: "Переместить {name} в архив?" channelArchiveConfirmDescription: "Архивированные каналы перестанут отображаться в списке каналов или результатах поиска. В них также нельзя будет добавлять новые записи." +thisChannelArchived: "Этот канал находится в архиве." displayOfNote: "Отображение заметок" initialAccountSetting: "Настройка профиля" youFollowing: "Подписки" preventAiLearning: "Отказаться от использования в машинном обучении (Генеративный ИИ)" +preventAiLearningDescription: "Запросить краулеров не использовать опубликованный текст или изображения и т.д. для машинного обучения (Прогнозирующий / Генеративный ИИ) датасетов. Это достигается путём добавления \"noai\" HTTP-заголовка в ответ на соответствующий контент. Полного предотвращения через этот заголовок не избежать, так как он может быть просто проигнорирован." options: "Настройки ролей" specifyUser: "Указанный пользователь" +openTagPageConfirm: "Открыть страницу этого хештега?" +specifyHost: "Указать сайт" failedToPreviewUrl: "Предварительный просмотр недоступен" update: "Обновить" rolesThatCanBeUsedThisEmojiAsReaction: "Роли тех, кому можно использовать эти эмодзи как реакцию" rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Если здесь ничего не указать, в качестве реакции эту эмодзи сможет использовать каждый." +rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Эти роли должны быть общедоступными." +cancelReactionConfirm: "Вы действительно хотите удалить свою реакцию?" later: "Позже" goToMisskey: "К Misskey" additionalEmojiDictionary: "Дополнительные словари эмодзи" installed: "Установлено" branding: "Бренд" +enableServerMachineStats: "Опубликовать характеристики сервера" enableIdenticonGeneration: "Включить генерацию иконки пользователя" turnOffToImprovePerformance: "Отключение этого параметра может повысить производительность." +createInviteCode: "Создать код приглашения" +createCount: "Количество приглашений" expirationDate: "Дата истечения" -unused: "Неиспользуемый" +noExpirationDate: "Бессрочно" +unused: "Неиспользованное" +used: "Использован" expired: "Срок действия приглашения истёк" doYouAgree: "Согласны?" icon: "Аватар" replies: "Ответы" renotes: "Репост" loadReplies: "Показать ответы" +pinnedList: "Закреплённый список" +keepScreenOn: "Держать экран включённым" +showRenotes: "Показывать репосты" +mutualFollow: "Взаимные подписки" +followingOrFollower: "Подписки или подписчики" +fileAttachedOnly: "Только заметки с файлами" +showRepliesToOthersInTimeline: "Показывать ответы в ленте" +showRepliesToOthersInTimelineAll: "Показывать в ленте ответы пользователей, на которых вы подписаны" +hideRepliesToOthersInTimelineAll: "Скрывать в ленте ответы пользователей, на которых вы подписаны" sourceCode: "Исходный код" +sourceCodeIsNotYetProvided: "Исходный код пока не доступен. Свяжитесь с администратором, чтобы исправить эту проблему." +repositoryUrl: "Ссылка на репозиторий" +repositoryUrlDescription: "Если вы используете Misskey как есть (без изменений в исходном коде), введите https://github.com/misskey-dev/misskey" +privacyPolicy: "Политика Конфиденциальности" +privacyPolicyUrl: "Ссылка на Политику Конфиденциальности" +attach: "Прикрепить" +angle: "Угол" flip: "Переворот" +disableStreamingTimeline: "Отключить обновление ленты в режиме реального времени" +useGroupedNotifications: "Отображать уведомления сгруппировано" +doReaction: "Добавить реакцию" code: "Код" +remainingN: "Остаётся: {n}" +seasonalScreenEffect: "Эффект времени года на экране" +decorate: "Украсить" +addMfmFunction: "Добавить MFM" lastNDays: "Последние {n} сут" +hemisphere: "Место проживания" +enableHorizontalSwipe: "Смахните в сторону, чтобы сменить вкладки" surrender: "Этот пост не может быть отменен." +useNativeUIForVideoAudioPlayer: "Использовать интерфейс браузера при проигрывании видео и звука" +keepOriginalFilename: "Сохранять исходное имя файла" +keepOriginalFilenameDescription: "Если вы выключите данную настройку, имена файлов будут автоматически заменены случайной строкой при загрузке." +alwaysConfirmFollow: "Всегда подтверждать подписку" +inquiry: "Связаться" _delivery: stop: "Заморожено" _type: none: "Публикация" +_announcement: + tooManyActiveAnnouncementDescription: "Большое количество оповещений может ухудшить пользовательский опыт. Рассмотрите архивирование неактуальных оповещений. " _initialAccountSetting: accountCreated: "Аккаунт успешно создан!" letsStartAccountSetup: "Давайте настроим вашу учётную запись." profileSetting: "Настройки профиля" privacySetting: "Настройки конфиденциальности" initialAccountSettingCompleted: "Первоначальная настройка успешно завершена!" + startTutorial: "Пройти Обучение" skipAreYouSure: "Пропустить настройку?" _initialTutorial: + launchTutorial: "Пройти обучение" _note: description: "Посты в Misskey называются 'Заметками.' Заметки отсортированы в хронологическом порядке в ленте и обновляются в режиме реального времени." + _reaction: + reactToContinue: "Добавьте реакцию, чтобы продолжить." + _postNote: + _visibility: + public: "Твоя заметка будет видна всем." + doNotSendConfidencialOnDirect2: "Администратор целевого сервера может видеть что вы отправляете. Будьте осторожны с конфиденциальной информацией, когда отправляете личные заметки пользователям с ненадёжных серверов." _timelineDescription: home: "В персональной ленте располагаются заметки тех, на которых вы подписаны." - local: "Местная лента показывает заметки всех пользователей этого сайта." + local: "Местная лента показывает заметки всех пользователей этого экземпляра." social: "В социальной ленте собирается всё, что есть в персональной и местной лентах." - global: "В глобальную ленту попадает вообще всё со связанных инстансов." + global: "В глобальную ленту попадает вообще всё со связанных экземпляров." _serverSettings: iconUrl: "Адрес на иконку роли" +_accountMigration: + moveFrom: "Перенести другую учётную запись сюда" + moveTo: "Перенести учётную запись на другой сервер" + moveAccountDescription: "Это действие перенесёт ваш аккаунт на другой сервер.\n ・Подписчики с этого аккаунта автоматически подпишутся на новый\n ・Этот аккаунт отпишется от всех пользователей, на которых подписан сейчас\n ・Вы не сможете создавать новые заметки и т.д. на этом аккаунте\n\nТогда как перенос подписчиков происходит автоматически, вы должны будете подготовиться, сделав некоторые шаги, чтобы перенести список пользователей, на которых вы подписаны. Чтобы сделать это, экспортируйте список подписчиков в файл, который затем импортируете на новом аккаунте в меню настроек. То же самое необходимо будет сделать со списками, также как и со скрытыми и заблокированными пользователями.\n\n(Это объяснение применяется к Misskey v13.12.0 и выше. Другое ActivityPub программное обеспечение, такое, как Mastodon, может работать по-другому." + startMigration: "Перенести" + movedAndCannotBeUndone: "Аккаунт был перемещён. Это действие необратимо." _achievements: earnedAt: "Разблокировано в" _types: @@ -1395,6 +1483,7 @@ _role: canPublicNote: "Может публиковать общедоступные заметки" canInvite: "Может создавать пригласительные коды" canManageCustomEmojis: "Управлять пользовательскими эмодзи" + canManageAvatarDecorations: "Управление украшениями аватара" driveCapacity: "Доступное пространство на «диске»" alwaysMarkNsfw: "Всегда отмечать файлы как «не для всех»" pinMax: "Доступное количество закреплённых заметок" @@ -1505,6 +1594,11 @@ _aboutMisskey: donate: "Пожертвование на Misskey" morePatrons: "Большое спасибо и многим другим, кто принял участие в этом проекте! 🥰" patrons: "Материальная поддержка" + projectMembers: "Участники проекта" +_displayOfSensitiveMedia: + respect: "Скрывать содержимое не для всех" + ignore: "Показывать содержимое не для всех" + force: "Скрывать всё содержимое" _instanceTicker: none: "Не показывать" remote: "Только для других сайтов" @@ -1533,7 +1627,7 @@ _wordMute: muteWordsDescription: "Пишите слова через пробел в одной строке, чтобы фильтровать их появление вместе; а если хотите фильтровать любое из них, пишите в отдельных строках." muteWordsDescription2: "Здесь можно использовать регулярные выражения — просто заключите их между двумя дробными чертами (/)." _instanceMute: - instanceMuteDescription: "Заметки и репосты с указанных здесь инстансов, а также ответы пользователям оттуда же не будут отображаться." + instanceMuteDescription: "Любые активности, затрагивающие инстансы из данного списка, будут скрыты." instanceMuteDescription2: "Пишите каждый инстанс на отдельной строке" title: "Скрывает заметки с заданных инстансов." heading: "Список скрытых инстансов" @@ -1582,7 +1676,7 @@ _theme: navActive: "Текст на боковой панели (активирован)" navIndicator: "Индикатор на боковой панели" link: "Ссылка" - hashtag: "Хэштег" + hashtag: "Хештег" mention: "Упоминание" mentionMe: "Упоминания вас" renote: "Репост" @@ -1600,7 +1694,6 @@ _theme: buttonBg: "Фон кнопки" buttonHoverBg: "Текст кнопки" inputBorder: "Рамка поля ввода" - listItemHoverBg: "Фон пункта списка (под указателем)" driveFolderBg: "Фон папки «Диска»" wallpaperOverlay: "Слой обоев" badge: "Значок" @@ -1612,8 +1705,10 @@ _sfx: note: "Заметки" noteMy: "Собственные заметки" notification: "Уведомления" - antenna: "Антенна" - channel: "Канал" + reaction: "При выборе реакции" +_soundSettings: + driveFile: "Использовать аудиофайл с Диска." + driveFileWarn: "Выбрать аудиофайл с Диска." _ago: future: "Из будущего" justNow: "Только что" @@ -1692,6 +1787,7 @@ _permissions: "write:gallery": "Редактирование галереи" "read:gallery-likes": "Просмотр списка понравившегося в галерее" "write:gallery-likes": "Изменение списка понравившегося в галерее" + "write:admin:reset-password": "Сбросить пароль пользователю" _auth: shareAccessTitle: "Разрешения для приложений" shareAccess: "Дать доступ для «{name}» к вашей учётной записи?" @@ -1745,6 +1841,7 @@ _widgets: _userList: chooseList: "Выберите список" clicker: "Счётчик щелчков" + birthdayFollowings: "Пользователи, у которых сегодня день рождения" _cw: hide: "Спрятать" show: "Показать" @@ -1798,7 +1895,7 @@ _profile: name: "Имя" username: "Имя пользователя" description: "О себе" - youCanIncludeHashtags: "Можете использовать здесь хэштеги" + youCanIncludeHashtags: "Можете использовать здесь хештеги." metadata: "Дополнительные сведения" metadataEdit: "Редактировать дополнительные сведения" metadataDescription: "Можно добавить до четырёх дополнительных граф в профиль." @@ -1806,6 +1903,8 @@ _profile: metadataContent: "Содержимое" changeAvatar: "Поменять аватар" changeBanner: "Поменять изображение в шапке" + verifiedLinkDescription: "Указывая здесь URL, содержащий ссылку на профиль, иконка владения ресурсом может быть отображена рядом с полем" + avatarDecorationMax: "Вы можете добавить до {max} украшений." _exportOrImport: allNotes: "Все заметки\n" favoritedNotes: "Избранное" @@ -1928,6 +2027,9 @@ _notification: unreadAntennaNote: "Антенна {name}" emptyPushNotificationMessage: "Обновлены push-уведомления" achievementEarned: "Получено достижение" + checkNotificationBehavior: "Проверить внешний вид уведомления" + sendTestNotification: "Отправить тестовое уведомление" + flushNotification: "Очистить уведомления" _types: all: "Все" follow: "Подписки" @@ -1940,6 +2042,7 @@ _notification: receiveFollowRequest: "Получен запрос на подписку" followRequestAccepted: "Запрос на подписку одобрен" achievementEarned: "Получение достижений" + login: "Войти" app: "Уведомления из приложений" _actions: followBack: "отвечает взаимной подпиской" @@ -1979,15 +2082,57 @@ _dialog: _disabledTimeline: title: "Лента отключена" description: "Ваша текущая роль не позволяет пользоваться этой лентой." +_drivecleaner: + orderBySizeDesc: "Размеры файлов по убыванию" + orderByCreatedAtAsc: "По увеличению даты" _webhookSettings: createWebhook: "Создать вебхук" + modifyWebhook: "Изменить Вебхук" name: "Название" + secret: "Секрет" + trigger: "Условие срабатывания" active: "Вкл." + _events: + follow: "Когда подписались на пользователя" + followed: "Когда на вас подписались" + note: "Когда создали заметку" + reply: "Когда получили ответ на заметку" + renote: "Когда вас репостнули" + reaction: "Когда получили реакцию" + mention: "Когда вас упоминают" + _systemEvents: + abuseReport: "Когда приходит жалоба" + abuseReportResolved: "Когда разрешается жалоба" + userCreated: "Когда создан пользователь" + deleteConfirm: "Вы уверены, что хотите удалить этот Вебхук?" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Электронная почта" + webhook: "Вебхук" + _captions: + webhook: "Отправить уведомление Системному Вебхуку при получении или разрешении жалоб." + notifiedWebhook: "Используемый Вебхук" _moderationLogTypes: suspend: "Заморозить" addCustomEmoji: "Добавлено эмодзи" updateCustomEmoji: "Изменено эмодзи" deleteCustomEmoji: "Удалено эмодзи" + deleteDriveFile: "Файл удалён" resetPassword: "Сброс пароля:" + createInvitation: "Создать код приглашения" + createSystemWebhook: "Создать Системный Вебхук" + updateSystemWebhook: "Обновить Системый Вебхук" + deleteSystemWebhook: "Удалить Системный Вебхук" +_fileViewer: + url: "Ссылка" + attachedNotes: "Закреплённые заметки" +_dataSaver: + _code: + title: "Подсветка кода" +_hemisphere: + N: "Северное полушарие" + S: "Южное полушарие" + caption: "Используется для некоторых настроек клиента для определения сезона." _reversi: total: "Всего" diff --git a/locales/si-LK.yml b/locales/si-LK.yml index e130d68ed8..c43f3d860d 100644 --- a/locales/si-LK.yml +++ b/locales/si-LK.yml @@ -17,3 +17,6 @@ _sfx: note: "නෝට්" _profile: username: "පරිශීලක නාමය" +_notification: + _types: + login: "පිවිසෙන්න" diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 52f6bf142c..60ce45a6b9 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -454,7 +454,6 @@ uiLanguage: "Jazyk používateľského prostredia" aboutX: "O {x}" emojiStyle: "Štýl emoji" native: "Natívne" -disableDrawer: "Nepoužívať šuflíkové menu" showNoteActionsOnlyHover: "Ovládacie prvky poznámky sa zobrazujú len po nabehnutí myši" noHistory: "Žiadna história" signinHistory: "História prihlásení" @@ -632,10 +631,7 @@ abuseReported: "Vaše nahlásenie je odoslané. Veľmi pekne ďakujeme." reporter: "Nahlásil" reporteeOrigin: "Pôvod nahláseného" reporterOrigin: "Pôvod nahlasovača" -forwardReport: "Preposlať nahlásenie na server" -forwardReportIsAnonymous: "Namiesto vášho účtu bude zobrazený anonymný systémový účet na vzdialenom serveri ako autor nahlásenia." send: "Poslať" -abuseMarkAsResolved: "Označiť nahlásenia ako vyriešené" openInNewTab: "Otvoriť v novom tabe" openInSideView: "Otvoriť v bočnom paneli" defaultNavigationBehaviour: "Predvolené správanie navigácie" @@ -1112,7 +1108,6 @@ _theme: buttonBg: "Pozadie tlačidla" buttonHoverBg: "Pozadie tlačidla (pod kurzorom)" inputBorder: "Okraj vstupného poľa" - listItemHoverBg: "Pozadie položky zoznamu (pod kurzorom)" driveFolderBg: "Pozadie priečinu disku" wallpaperOverlay: "Vrstvenie pozadia" badge: "Odznak" @@ -1124,8 +1119,6 @@ _sfx: note: "Poznámky" noteMy: "Vlastná poznámka" notification: "Oznámenia" - antenna: "Antény" - channel: "Upozornenia kanála" _ago: future: "Budúcnosť" justNow: "Teraz" @@ -1412,6 +1405,7 @@ _notification: pollEnded: "Hlasovanie skončilo" receiveFollowRequest: "Doručené žiadosti o sledovanie" followRequestAccepted: "Schválené žiadosti o sledovanie" + login: "Prihlásiť sa" app: "Oznámenia z prepojených aplikácií" _actions: followBack: "Sledovať späť\n" @@ -1447,6 +1441,10 @@ _deck: _webhookSettings: name: "Názov" active: "Zapnuté" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: suspend: "Zmraziť" resetPassword: "Resetovať heslo" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index 089dc3949f..5a0de660e8 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -512,7 +512,6 @@ _theme: _sfx: note: "Noter" notification: "Notifikationer" - antenna: "Antenner" _2fa: renewTOTPCancel: "Nej tack" _antennaSources: @@ -563,6 +562,7 @@ _notification: renote: "Omnotera" quote: "Citat" reaction: "Reaktioner" + login: "Logga in" _actions: reply: "Svara" renote: "Omnotera" @@ -577,6 +577,10 @@ _deck: _webhookSettings: name: "Namn" active: "Aktiverad" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "E-post" _moderationLogTypes: suspend: "Suspendera" resetPassword: "Återställ Lösenord" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index ab09ac4d5a..c70d448e2b 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -2,10 +2,10 @@ _lang_: "ภาษาไทย" headlineMisskey: "เชื่อมต่อเครือข่ายโดยโน้ต" introMisskey: "ยินดีต้อนรับทุกคนจ้า! Misskey คือ ซอฟต์แวร์โอเพนซอร์สสำหรับบริการไมโครบล็อกกิ้ง (MicroBlogging) แบบกระจายศูนย์อำนาจ (Decentralized) \n\nเขียน “โน้ต (Note)” เพื่อส่งต่อเรื่องราวของคุณให้ทั้งโลกได้รับรู้📡\nและอย่าลืมที่จะ “รีแอคชั่น” กับเรื่องราวของคนอื่น ๆ ด้วยนะ! 👍\n\nท่องสำรวจโลกใบใหม่กันเถอะ🚀" -poweredByMisskeyDescription: "{name} เป็นส่วนหนึ่งในบริการที่ถูกขับเคลื่อนโดยแพลตฟอร์มโอเพ่นซอร์ส Misskey (เรียกว่า \"อินสแตนซ์ Misskey\")" +poweredByMisskeyDescription: "{name} เป็นหนึ่งในเซิร์ฟเวอร์ของแพลตฟอร์มโอเพ่นซอร์ส Misskey" monthAndDay: "{month}/{day}" search: "ค้นหา" -notifications: "การเเจ้งเตือน" +notifications: "เเจ้งเตือน" username: "ชื่อผู้ใช้" password: "รหัสผ่าน" forgotPassword: "ลืมรหัสผ่าน" @@ -18,7 +18,7 @@ enterUsername: "กรอกชื่อผู้ใช้" renotedBy: "รีโน้ตโดย {user}" noNotes: "ไม่มีโน้ต" noNotifications: "ไม่มีการแจ้งเตือน" -instance: "อินสแตนซ์" +instance: "เซิร์ฟเวอร์" settings: "การตั้งค่า" notificationSettings: "ตั้งค่าการแจ้งเตือน" basicSettings: "การตั้งค่าพื้นฐาน" @@ -48,7 +48,7 @@ copyLink: "คัดลอกลิงก์" copyLinkRenote: "คัดลอกลิงก์รีโน้ต" delete: "ลบ" deleteAndEdit: "ลบและแก้ไข" -deleteAndEditConfirm: "คุณต้องการลบโน้ตนี้และแก้ไขใหม่ใช่ไหม? รีแอคชั่น รีโน้ต และการตอบกลับต่อโน้ตนี้ทั้งหมดจะถูกลบออกด้วย" +deleteAndEditConfirm: "ต้องการลบโน้ตนี้และแก้ไขใหม่ใช่ไหม? รีแอคชั่น รีโน้ต และการตอบกลับต่อโน้ตนี้ทั้งหมดจะถูกลบออกด้วย" addToList: "เพิ่มลงรายชื่อ" addToAntenna: "เพิ่มไปยังเสาอากาศ" sendMessage: "ส่งข้อความ" @@ -60,6 +60,7 @@ copyFileId: "คัดลอกไฟล์ ID" copyFolderId: "คัดลอกโฟลเดอร์ ID" copyProfileUrl: "คัดลอกโปรไฟล์ URL" searchUser: "ค้นหาผู้ใช้" +searchThisUsersNotes: "ค้นหาโน้ตของผู้ใช้" reply: "ตอบกลับ" loadMore: "แสดงเพิ่มเติม" showMore: "แสดงเพิ่มเติม" @@ -68,7 +69,7 @@ youGotNewFollower: "ได้ติดตามคุณ" receiveFollowRequest: "มีคำขอติดตามส่งมาหา" followRequestAccepted: "การติดตามได้รับการอนุมัติแล้ว" mention: "กล่าวถึง" -mentions: "พูดถึง" +mentions: "กล่าวถึงคุณ" directNotes: "โพสต์แบบไดเร็กต์" importAndExport: "นำเข้า / ส่งออก" import: "นำเข้า" @@ -92,7 +93,7 @@ error: "ผิดพลาด!" somethingHappened: "อุ๊ย ! มีอะไรบางอย่างผิดพลาด" retry: "ลองใหม่อีกครั้ง" pageLoadError: "เกิดข้อผิดพลาดในการโหลดหน้านี้" -pageLoadErrorDescription: "โดยปกติแล้วมักจะเกิดจากข้อผิดพลาดของเครือข่ายหรือแคชของเบราว์เซอร์ ลองล้างแคชแล้วลองใหม่อีกครั้งหลังจากรอสักครู่ " +pageLoadErrorDescription: "ปัญหานี้มักเกิดจากแคชของเครือข่ายหรือเบราว์เซอร์ ควรล้างแคช, รอสักครู่ แล้วลองใหม่อีกครั้ง" serverIsDead: "เซิร์ฟเวอร์นี้ไม่มีการตอบสนอง โปรดกรุณารอสักครู่แล้วลองใหม่อีกครั้ง" youShouldUpgradeClient: "หากต้องการดูหน้านี้ กรุณาโหลดหน้าใหม่เพื่ออัปเดตไคลเอ็นต์ของคุณ" enterListName: "ป้อนนามเรียกของรายชื่อชุดนี้" @@ -108,11 +109,14 @@ enterEmoji: "พิมพ์เอโมจิ" renote: "รีโน้ต" unrenote: "เลิกรีโน้ต" renoted: "รีโน้ตแล้ว" +renotedToX: "รีโน้ตให้ {name} แล้ว" cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตใหม่ได้" cantReRenote: "รีโน้ตไม่สามารถรีโน้ตซ้ำได้" quote: "อ้างอิง" inChannelRenote: "รีโน้ตในช่องเท่านั้น" inChannelQuote: "อ้างอิงในช่องเท่านั้น" +renoteToChannel: "รีโน้ตไปที่ช่อง" +renoteToOtherChannel: "รีโน้ตไปยังช่องอื่น" pinnedNote: "โน้ตที่ปักหมุดไว้" pinned: "ปักหมุด" you: "คุณ" @@ -151,6 +155,7 @@ editList: "แก้ไขรายชื่อ" selectChannel: "เลือกช่อง" selectAntenna: "เลือกเสาอากาศ" editAntenna: "แก้ไขเสาอากาศ" +createAntenna: "สร้างเสาอากาศ" selectWidget: "เลือกวิดเจ็ต" editWidgets: "แก้ไขวิดเจ็ต" editWidgetsExit: "เรียบร้อย" @@ -163,20 +168,24 @@ addEmoji: "แทรกเอโมจิ" settingGuide: "การตั้งค่าที่แนะนำ" cacheRemoteFiles: "แคชไฟล์ระยะไกล" cacheRemoteFilesDescription: "หากเปิดใช้งาน ไฟล์ระยะไกลจะถูกแคชไว้ ทำให้แสดงภาพเร็วขึ้น แต่ก็ใช้พื้นที่เก็บข้อมูลของเซิร์ฟเวอร์มากขึ้นเช่นกัน สำหรับขีดจำกัดที่ผู้ใช้ระยะไกลถูกแคชไว้จะขึ้นอยู่กับความจุไดรฟ์ตามบทบาทของเขา เมื่อเกินแล้วไฟล์เก่าจะถูกลบออกและเก็บเป็นลิงก์แทน หากปิดใช้งาน ไฟล์ระยะไกลจะถูกเก็บเป็นลิงก์ตั้งแต่ต้น เราแนะนำให้ตั้งค่า proxyRemoteFiles ใน default.yml เป็น true เพื่อสร้างธัมบ์เนลและปกป้องความเป็นส่วนตัวของผู้ใช้" -youCanCleanRemoteFilesCache: "คุณสามารถล้างแคชได้โดยคลิกที่ปุ่ม 🗑️ ในมุมมองการจัดการไฟล์" +youCanCleanRemoteFilesCache: "สามารถลบแคชทั้งหมดได้โดยใช้ปุ่ม 🗑️ ในหน้าการจัดการไฟล์" cacheRemoteSensitiveFiles: "แคชไฟล์ระยะไกลที่มีเนื้อหาละเอียดอ่อน" -cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานการตั้งค่านี้ ไฟล์ระยะไกลที่มีเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกลโดยที่ไม่มีการแคช" +cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานการตั้งค่านี้ ไฟล์ระยะไกลที่มีเนื้อหาละเอียดอ่อนจะถูกโหลดโดยตรงจากเซิร์ฟเวอร์ระยะไกลโดยไม่มีการแคช" flagAsBot: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นบอต" -flagAsBotDescription: "การเปิดใช้งานตัวเลือกนี้หากบัญชีนี้ถูกควบคุมโดยนักเขียนโปรแกรม หรือ ถ้าหากเปิดใช้งาน มันจะทำหน้าที่เป็นแฟล็กสำหรับนักพัฒนารายอื่นๆ และเพื่อป้องกันการโต้ตอบแบบไม่มีที่สิ้นสุดกับบอทตัวอื่นๆ และยังสามารถปรับเปลี่ยนระบบภายในของ Misskey เพื่อปฏิบัติต่อบัญชีนี้เป็นบอท" +flagAsBotDescription: "เปิดใช้งานตัวเลือกนี้หากบัญชีนี้ถูกควบคุมโดยโปรแกรม เมื่อเปิดใช้งาน มันจะทำหน้าที่เป็นแฟล็กสำหรับนักพัฒนารายอื่นในการป้องกันการสร้างห่วงโซ่การโต้ตอบแบบอนันต์กับบอตตัวอื่น และปรับระบบภายในของ Misskey เพื่อจัดการบัญชีนี้ในฐานะบอต" flagAsCat: "เมี้ยววววววววววววววว!!!!!!!!!!!" flagAsCatDescription: "เหมียวเหมียวเมี้ยว??" -flagShowTimelineReplies: "แสดงตอบกลับ ในไทม์ไลน์" -flagShowTimelineRepliesDescription: "แสดงการตอบกลับของผู้ใช้งานไปยังโน้ตของผู้ใช้งานรายอื่นๆในไทม์ไลน์หากได้เปิดเอาไว้" -autoAcceptFollowed: "อนุมัติคำขอติดตามโดยอัตโนมัติทันที จากผู้ใช้งานที่คุณกำลังติดตาม" +flagShowTimelineReplies: "แสดงตอบกลับโน้ตลงไทม์ไลน์" +flagShowTimelineRepliesDescription: "เมื่อเปิดใช้งาน จะแสดงการตอบกลับของผู้ใช้คนนั้นต่อโน้ตอื่นๆ ในไทม์ไลน์ด้วย" +autoAcceptFollowed: "อนุมัติคำขอติดตามจากผู้ใช้ที่คุณติดตามอยู่โดยอัตโนมัติ" addAccount: "เพิ่มบัญชี" reloadAccountsList: "รีโหลดรายการบัญชีใหม่" loginFailed: "การเข้าสู่ระบบไม่สำเร็จ" -showOnRemote: "ดูบนอินสแตนซ์ระยะไกล" +showOnRemote: "ดูบนเซิร์ฟเวอร์ฝั่งระยะไกล" +continueOnRemote: "ดำเนินการต่อบนเซิร์ฟเวอร์ฝั่งระยะไกล" +chooseServerOnMisskeyHub: "เลือกเซิร์ฟเวอร์จาก Misskey Hub" +specifyServerHost: "ระบุโดเมนของเซิร์ฟเวอร์โดยตรง" +inputHostName: "โปรดป้อนโดเมน" general: "ทั่วไป" wallpaper: "ภาพพื้นหลัง" setWallpaper: "ตั้งค่าภาพพื้นหลัง" @@ -185,23 +194,25 @@ searchWith: "ค้นหา: {q}" youHaveNoLists: "คุณไม่มีรายชื่อใดๆ " followConfirm: "ต้องการติดตาม {name} ใช่ไหม?" proxyAccount: "บัญชีพร็อกซี่" -proxyAccountDescription: "บัญชีพร็อกซี่ คือ บัญชีที่จะทำหน้าที่เป็นผู้ติดตามระยะไกลสำหรับผู้ใช้งานที่อยู่ภายใต้ด้วยเงื่อนไขบางอย่าง ยกตัวอย่าง เช่น เมื่อมีผู้ใช้งานนั้นได้เพิ่มผู้ใช้งานจากระยะไกลลงในรายการ แต่กิจกรรมของผู้ใช้ในระยะไกลนั้นจะไม่ถูกส่งไปยังอินสแตนซ์หากไม่มีผู้ใช้งานในพื้นที่ติดตามผู้ใช้รายนั้น ดังนั้นบัญชีพร็อกซีนี้จะติดตามแทน" +proxyAccountDescription: "บัญชีพร็อกซี คือ บัญชีที่ทำหน้าที่ติดตาม(ผู้ใช้)ระยะไกลภายใต้เงื่อนไขบางประการ ตัวอย่างเช่น เมื่อผู้ใช้ท้องถิ่นเพิ่มผู้ใช้ระยะไกลลงรายชื่อ หากไม่มีใครติดตามผู้ใช้ระยะไกลในรายชื่อนั้น กิจกรรมก็จะไม่ถูกส่งมายังเซิร์ฟเวอร์ ดังนั้นจึงมีบัญชีพร็อกซีไว้ติดตามผู้ใช้ระยะไกลเหล่านั้น" host: "โฮสต์" +selectSelf: "เลือกตัวเอง" selectUser: "เลือกผู้ใช้งาน" recipient: "ผู้รับ" annotation: "หมายเหตุประกอบ" federation: "สหพันธ์" -instances: "อินสแตนซ์" +instances: "เซิร์ฟเวอร์" registeredAt: "วันที่ลงทะเบียน" latestRequestReceivedAt: "คำขอล่าสุดที่ได้รับ" latestStatus: "สถานะล่าสุด" storageUsage: "พื้นที่จัดเก็บข้อมูลที่ใช้ไป" -charts: "โดดเด่น" -perHour: "ทุกชั่วโมง" +charts: "แผนภูมิ" +perHour: "ต่อชั่วโมง" perDay: "ต่อวัน" stopActivityDelivery: "หยุดส่งกิจกรรม" -blockThisInstance: "บล็อกอินสแตนซ์นี้" -silenceThisInstance: "ปิดปากอินสแตนซ์นี้" +blockThisInstance: "บล็อกเซิร์ฟเวอร์นี้" +silenceThisInstance: "ปิดปากเซิร์ฟเวอร์นี้" +mediaSilenceThisInstance: "ปิดปากสื่อของเซิร์ฟเวอร์นี้" operations: "ดำเนินการ" software: "ซอฟต์แวร์" version: "เวอร์ชั่น" @@ -212,17 +223,19 @@ jobQueue: "คิวงาน" cpuAndMemory: "ซีพียู และ หน่วยความจำ" network: "เครือข่าย" disk: "ดิสก์" -instanceInfo: "ข้อมูลอินสแตนซ์" +instanceInfo: "ข้อมูลเซิร์ฟเวอร์" statistics: "สถิติการใช้งาน" clearQueue: "ล้างคิว" clearQueueConfirmTitle: "ต้องการล้างคิวใช่ไหม?" clearQueueConfirmText: "โพสต์ที่ยังค้างในคิวจะไม่ถูกจัดส่งอีกต่อไป โดยปกติแล้วการดำเนินการนี้ไม่จำเป็น" clearCachedFiles: "ล้างแคช" clearCachedFilesConfirm: "ต้องการลบไฟล์ระยะไกลที่แคชไว้ทั้งหมดใช่ไหม?" -blockedInstances: "อินสแตนซ์ที่ถูกบล็อก" -blockedInstancesDescription: "ระบุชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการบล็อก อินสแตนซ์ที่อยู่ในรายการนั้นจะไม่สามารถพูดคุยกับอินสแตนซ์นี้ได้อีกต่อไป" -silencedInstances: "ปิดปากอินสแตนซ์นี้แล้ว" -silencedInstancesDescription: "ตั้งค่ารายชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการปิดปาก บัญชีทั้งหมดของอินสแตนซ์ที่อยู่ในรายชื่อนั้นๆ จะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในพื้นที่ได้หากไม่ได้ติดตาม | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก" +blockedInstances: "เซิร์ฟเวอร์ที่ถูกบล็อก" +blockedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการบล็อก คั่นด้วยการขึ้นบรรทัดใหม่ เซิร์ฟเวอร์ที่ถูกบล็อกจะไม่สามารถติดต่อกับอินสแตนซ์นี้ได้" +silencedInstances: "ปิดปากเซิร์ฟเวอร์นี้แล้ว" +silencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปาก คั่นด้วยการขึ้นบรรทัดใหม่, บัญชีทั้งหมดของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในเซิร์ฟเวอร์นี้ได้หากไม่ได้ถูกติดตามกลับ | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก" +mediaSilencedInstances: "เซิร์ฟเวอร์ที่ถูกปิดปากสื่อ" +mediaSilencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปากสื่อ คั่นด้วยการขึ้นบรรทัดใหม่, ไฟล์ที่ถูกส่งจากบัญชีของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปาก แล้วจะถูกติดเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน และเอโมจิแบบกำหนดเองก็จะใช้ไม่ได้ด้วย | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก" muteAndBlock: "ปิดเสียงและบล็อก" mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง" blockedUsers: "ผู้ใช้ที่ถูกบล็อก" @@ -240,14 +253,14 @@ noCustomEmojis: "ไม่มีเอโมจิ" noJobs: "ไม่มีงาน" federating: "สหพันธ์" blocked: "ถูกบล็อก" -suspended: "ถูกระงับ" +suspended: "ระงับการส่ง" all: "ทั้งหมด" -subscribing: "สมัครแล้ว" +subscribing: "กำลังสมัครสมาชิก" publishing: "กำลังเผยแพร่" notResponding: "ไม่มีการตอบสนอง" -instanceFollowing: "กำลังติดตามบนอินสแตนซ์" -instanceFollowers: "ผู้ติดตามของอินสแตนซ์" -instanceUsers: "ผู้ใช้งานของอินสแตนซ์นี้" +instanceFollowing: "กำลังติดตามบนเซิร์ฟเวอร์" +instanceFollowers: "ผู้ติดตามของเซิร์ฟเวอร์" +instanceUsers: "ผู้ใช้ของเซิร์ฟเวอร์นี้" changePassword: "เปลี่ยนรหัสผ่าน" security: "ความปลอดภัย" retypedNotMatch: "ทั้งสองป้อนข้อมูลไม่สอดคล้องกัน" @@ -284,20 +297,20 @@ messageRead: "อ่านแล้ว" noMoreHistory: "ไม่มีประวัติเพิ่มเติม" startMessaging: "เริ่มการสนทนา" nUsersRead: "อ่านโดย {n}" -agreeTo: "ฉันยอมรับที่จะ {0}" +agreeTo: "ฉันยอมรับ {0}" agree: "ยอมรับ" -agreeBelow: "ฉันยอมรับถึงด้านล่าง" +agreeBelow: "ยอมรับตามที่ระบุด้านล่าง" basicNotesBeforeCreateAccount: "หมายเหตุสำคัญ" termsOfService: "เงื่อนไขการให้บริการ" start: "เริ่ม" -home: "หน้าแรก" -remoteUserCaution: "ข้อมูลอาจไม่สมบูรณ์เนื่องจากผู้ใช้รายนี้มาจากอินสแตนซ์ระยะไกล" +home: "หน้าหลัก" +remoteUserCaution: "ข้อมูลอาจไม่สมบูรณ์เนื่องจากผู้ใช้รายนี้มาจากเซิร์ฟเวอร์ระยะไกล" activity: "กิจกรรม" images: "รูปภาพ" image: "รูปภาพ" birthday: "วันเกิด" yearsOld: "{age} ปี" -registeredDate: "วันที่สมัครสมาชิก" +registeredDate: "วันที่ลงทะเบียน" location: "ตำแหน่งที่ตั้ง" theme: "ธีม" themeForLightMode: "ธีมที่จะใช้ในโหมดสว่าง" @@ -313,6 +326,7 @@ selectFile: "เลือกไฟล์" selectFiles: "เลือกไฟล์" selectFolder: "เลือกโฟลเดอร์" selectFolders: "เลือกโฟลเดอร์" +fileNotSelected: "ยังไม่ได้เลือกไฟล์" renameFile: "เปลี่ยนชื่อไฟล์" folderName: "ชื่อโฟลเดอร์" createFolder: "สร้างโฟลเดอร์" @@ -336,15 +350,15 @@ displayOfSensitiveMedia: "แสดงสื่อที่มีเนื้อ whenServerDisconnected: "เมื่อสูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์" disconnectedFromServer: "การเชื่อมต่อเซิร์ฟเวอร์ถูกตัด" reload: "รีโหลด" -doNothing: "เมิน" +doNothing: "ช่างมัน" reloadConfirm: "รีโหลดเลยไหม?" -watch: "ดู" -unwatch: "หยุดดู" +watch: "เพ่งเล็ง" +unwatch: "เลิกเพ่งเล็ง" accept: "ยอมรับ" reject: "ปฏิเสธ" normal: "ปกติ" -instanceName: "ชื่ออินสแตนซ์" -instanceDescription: "คำอธิบายอินสแตนซ์" +instanceName: "ชื่อเซิร์ฟเวอร์" +instanceDescription: "คำอธิบายแนะนำเซิร์ฟเวอร์" maintainerName: "ผู้ดูแล" maintainerEmail: "อีเมลผู้ดูแลระบบ" tosUrl: "URL เงื่อนไขการให้บริการ" @@ -355,16 +369,16 @@ dayX: "{day}" monthX: "เดือน {month}" yearX: "{year}" pages: "หน้าเพจ" -integration: "รวบรวม" +integration: "เชื่อมโยง" connectService: "เชื่อมต่อ" disconnectService: "ตัดการเชื่อมต่อ" -enableLocalTimeline: "เปิดใช้งานไทม์ไลน์ในพื้นที่" +enableLocalTimeline: "เปิดใช้งานไทม์ไลน์ท้องถิ่น" enableGlobalTimeline: "เปิดใช้งานไทม์ไลน์ทั่วโลก" disablingTimelinesInfo: "ผู้ดูแลระบบและผู้ควบคุมจะสามารถเข้าถึงไทม์ไลน์ทั้งหมด ถึงแม้ว่าจะไม่ได้เปิดใช้งานก็ตาม" registration: "ลงทะเบียน" enableRegistration: "เปิดใช้งานการลงทะเบียนผู้ใช้ใหม่" invite: "คำเชิญ" -driveCapacityPerLocalAccount: "ความจุของไดรฟ์ต่อผู้ใช้ภายในเครื่อง" +driveCapacityPerLocalAccount: "ความจุของไดรฟ์ต่อผู้ใช้ท้องถิ่น" driveCapacityPerRemoteAccount: "ความจุของไดรฟ์ต่อผู้ใช้ระยะไกล" inMb: "เป็นเมกะไบต์" bannerUrl: "URL รูปภาพแบนเนอร์" @@ -373,7 +387,7 @@ basicInfo: "ข้อมูลเบื้องต้น" pinnedUsers: "ผู้ใช้ที่ถูกปักหมุด" pinnedUsersDescription: "ป้อนชื่อผู้ใช้ที่คุณต้องการปักหมุดในหน้า “ค้นพบ” ฯลฯ คั่นด้วยการขึ้นบรรทัดใหม่" pinnedPages: "หน้าเพจที่ปักหมุด" -pinnedPagesDescription: "ป้อนเส้นทางของหน้าเพจที่คุณต้องการปักหมุดไว้ที่หน้าแรกของอินสแตนซ์นี้ คั่นด้วยขึ้นบรรทัดใหม่" +pinnedPagesDescription: "ป้อนเส้นทางของหน้าเพจที่คุณต้องการปักหมุดไว้ที่หน้าแรกของเซิร์ฟเวอร์นี้ คั่นด้วยการขึ้นบรรทัดใหม่" pinnedClipId: "ID ของคลิปที่จะปักหมุด" pinnedNotes: "โน้ตที่ปักหมุดไว้" hcaptcha: "hCaptcha" @@ -389,11 +403,11 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "เปิดใช้ reCAPTCHA" recaptchaSiteKey: "คีย์ไซต์" recaptchaSecretKey: "คีย์ลับ" -turnstile: "เทิร์น'สไทล" -enableTurnstile: "เปิดใช้งาน เทิร์น'สไทล" +turnstile: "Turnstile" +enableTurnstile: "เปิดใช้งาน Turnstile" turnstileSiteKey: "คีย์ไซต์" turnstileSecretKey: "คีย์ลับ" -avoidMultiCaptchaConfirm: "การใช้ระบบ Captcha หลายระบบอาจทำให้เกิดการรบกวนหรืออาจจะเกิดข้อผิดพลาดได้ หากต้องการที่จะปิดการใช้งานระบบ Captcha อื่น ๆ แนะนำให้ปิดตัวอื่นๆก่อน ถ้าหากคุณต้องการให้เปิดใช้งานต่อไป ให้ กด ยกเลิก" +avoidMultiCaptchaConfirm: "การใช้ Captcha หลายตัวอาจทำให้เกิดการรบกวนหรือข้อผิดพลาดได้ ต้องการที่จะปิดการใช้งาน Captcha ตัวอื่นเลยไหม? หากต้องการให้เปิดใช้งานต่อไป ให้กดยกเลิก" antennas: "เสาอากาศ" manageAntennas: "จัดการเสาอากาศ" name: "ชื่อ" @@ -401,7 +415,7 @@ antennaSource: "แหล่งเสาอากาศ" antennaKeywords: "คีย์เวิร์ดที่ควรฟัง" antennaExcludeKeywords: "คีย์เวิร์ดที่จะยกเว้น" antennaExcludeBots: "ยกเว้นบัญชีบอต" -antennaKeywordsDescription: "คั่นด้วยช่องว่างสำหรับเงื่อนไข AND หรือด้วยการขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR" +antennaKeywordsDescription: "คั่นด้วยเว้นวรรคสำหรับเงื่อนไข AND, หรือขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR" notifyAntenna: "แจ้งเตือนเกี่ยวกับโน้ตใหม่" withFileAntenna: "เฉพาะโน้ตที่มีไฟล์" enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์ของคุณ" @@ -418,7 +432,7 @@ unsilenceConfirm: "ต้องการเลิกปิดปากผู้ popularUsers: "ผู้ใช้ที่เป็นที่นิยม" recentlyUpdatedUsers: "ผู้ใช้ที่เพิ่งใช้งานล่าสุด" recentlyRegisteredUsers: "ผู้ใช้ที่เข้าร่วมใหม่" -recentlyDiscoveredUsers: "ผู้ใช้ที่เพิ่งค้นพบใหม่" +recentlyDiscoveredUsers: "ผู้ใช้ที่เพิ่งค้นพบล่าสุด" exploreUsersCount: "มีผู้ใช้ {count} ราย" exploreFediverse: "สำรวจสหพันธ์" popularTags: "แท็กยอดนิยม" @@ -435,7 +449,7 @@ moderator: "ผู้ควบคุม" moderation: "การกลั่นกรอง" moderationNote: "โน้ตการกลั่นกรอง" addModerationNote: "เพิ่มโน้ตการกลั่นกรอง" -moderationLogs: "ปูมการแก้ไข" +moderationLogs: "ปูมการควบคุมดูแล" nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} ราย" securityKeyAndPasskey: "ความปลอดภัยและรหัสผ่าน" securityKey: "กุญแจความปลอดภัย" @@ -468,44 +482,45 @@ retype: "พิมพ์รหัสอีกครั้ง" noteOf: "โน้ตของ {user}" quoteAttached: "อ้างอิง" quoteQuestion: "ต้องการที่จะแนบมันเพื่ออ้างอิงใช่ไหม?" +attachAsFileQuestion: "ข้อความในคลิปบอร์ดยาวเกินไป คุณต้องการแนบเป็นไฟล์ข้อความหรือไม่?" noMessagesYet: "ยังไม่มีข้อความ" newMessageExists: "คุณมีข้อความใหม่" onlyOneFileCanBeAttached: "สามารถแนบไฟล์ได้เพียงไฟล์เดียวต่อ 1 ข้อความ" -signinRequired: "กรุณาลงทะเบียนหรือลงชื่อเข้าใช้ก่อนดำเนินการต่อ" +signinRequired: "ก่อนดำเนินการต่อ กรุณาลงทะเบียนหรือเข้าสู่ระบบ" +signinOrContinueOnRemote: "เพื่อดำเนินการต่อได้ คุณต้องไปที่เซิร์ฟเวอร์ที่คุณใช้งานอยู่ หรือลงทะเบียน/เข้าสู่ระบบเซิร์ฟเวอร์นี้" invitations: "คำเชิญ" invitationCode: "รหัสเชิญ" checking: "Checking" available: "พร้อมใช้งาน" unavailable: "ไม่พร้อมใช้" -usernameInvalidFormat: "คุณสามารถใช้อักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก ตัวเลข และขีดล่างได้นะ ( a-z , A-Z , 0-9 , รวมไปถึงอักษรพิเศษเช่น + * / , . - อื่นๆเป็นต้น )" +usernameInvalidFormat: "สามารถใช้ a~z A~Z 0~9 และ _ ได้" tooShort: "สั้นเกินไปนะ" tooLong: "ยาวเกินไปนะ" -weakPassword: "รหัสผ่าน แย่มาก" +weakPassword: "รหัสผ่านแย่มาก" normalPassword: "รหัสผ่านปกติ" strongPassword: "รหัสผ่านรัดกุมมาก" passwordMatched: "ถูกต้อง!" passwordNotMatched: "ไม่ถูกต้อง" -signinWith: "ลงชื่อเข้าใช้ด้วย {x}" -signinFailed: "ไม่สามารถลงชื่อผู้เข้าใช้ได้ เนื่องจาก ชื่อผู้ใช้หรือรหัสผ่านที่คุณป้อนนั้นไม่ถูกต้องนะ" +signinWith: "เข้าสู่ระบบด้วย {x}" +signinFailed: "ไม่สามารถเข้าสู่ระบบได้ กรุณาตรวจสอบชื่อผู้ใช้และรหัสผ่าน" or: "หรือ" language: "ภาษา" uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้งาน" aboutX: "เกี่ยวกับ {x}" -emojiStyle: "สไตล์เอโมจิ" +emojiStyle: "สไตล์ของเอโมจิ" native: "ภาษาแม่" -disableDrawer: "อย่าใช้ลิ้นชักสไตล์เมนู" -showNoteActionsOnlyHover: "แสดงการดำเนินการเฉพาะโน้ตเมื่อโฮเวอร์" +showNoteActionsOnlyHover: "แสดงการดำเนินการโน้ตเมื่อโฮเวอร์(วางเมาส์เหนือ)เท่านั้น" showReactionsCount: "แสดงจำนวนรีแอกชั่นในโน้ต" noHistory: "ไม่มีประวัติ" signinHistory: "ประวัติการเข้าสู่ระบบ" enableAdvancedMfm: "เปิดใช้งาน MFM ขั้นสูง" -enableAnimatedMfm: "เปิดการใช้งาน MFM ด้วยแอนิเมชั่น" +enableAnimatedMfm: "เปิดการใช้งาน MFM แบบเคลื่อนไหว" doing: "กำลังประมวลผล......" category: "หมวดหมู่" tags: "นามแฝง" docSource: "ที่มาของเอกสารนี้" createAccount: "สร้างบัญชี" -existingAccount: "บัญชีที่มีอยู่" +existingAccount: "บัญชีที่มีอยู่แล้ว" regenerate: "สร้างอีกครั้ง" fontSize: "ขนาดตัวอักษร" mediaListWithOneImageAppearance: "ความสูงของรายการสื่อที่มีเพียงรูปเดียว" @@ -513,11 +528,11 @@ limitTo: "จำกัดไว้ที่ {x}" noFollowRequests: "คุณไม่มีคำขอติดตามที่รอดำเนินการ" openImageInNewTab: "เปิดรูปภาพในแท็บใหม่" dashboard: "หน้ากระดานหลัก" -local: "ในพื้นที่" +local: "ท้องถิ่น" remote: "ระยะไกล" total: "รวมทั้งหมด" -weekOverWeekChanges: "เปลี่ยนแปลงไปเมื่อสัปดาห์ที่แล้ว" -dayOverDayChanges: "เปลี่ยนแปลงไปเมื่อวานนี้" +weekOverWeekChanges: "เทียบกับสัปดาห์ก่อน" +dayOverDayChanges: "เทียบกับเมื่อวาน" appearance: "ภาพลักษณ์" clientSettings: "การตั้งค่าไคลเอนต์" accountSettings: "ตั้งค่าบัญชี" @@ -531,19 +546,19 @@ useObjectStorage: "ใช้การจัดเก็บในรูปแบ objectStorageBaseUrl: "Base URL" objectStorageBaseUrlDesc: "URL ที่ใช้เป็นข้อมูลอ้างอิง ระบุ URL ของ CDN หรือ Proxy ถ้าหากคุณใช้อย่างใดอย่างหนึ่ง\n สำหรับการใช้งาน S3 'https://.s3.amazonaws.com' และสำหรับ GCS หรือบริการที่เทียบเท่าใช้ 'https://storage.googleapis.com/', เป็นต้น" objectStorageBucket: "Bucket" -objectStorageBucketDesc: "โปรดระบุชื่อที่เก็บข้อมูลที่ใช้กับผู้ให้บริการของคุณ" +objectStorageBucketDesc: "โปรดระบุชื่อบัคเก็ตของบริการที่ใช้อยู่" objectStoragePrefix: "คำนำหน้า" objectStoragePrefixDesc: "ไฟล์ทั้งหมดจะถูกเก็บไว้ภายใต้ไดเร็กทอรีที่มีคำนำหน้านี้" objectStorageEndpoint: "ปลายทาง" objectStorageEndpointDesc: "เว้นว่างไว้หากคุณใช้ AWS S3 หรือระบุปลายทางเป็น '' หรือ ':' ทั้งนี้ขึ้นอยู่กับผู้ให้บริการที่คุณใช้อยู่ด้วย" objectStorageRegion: "ภูมิภาค" -objectStorageRegionDesc: "ระบุภูมิภาค เช่น 'xx-east-1' ถ้าหากบริการของคุณไม่ได้แยกความแตกต่างระหว่างภูมิภาคก็ให้ เว้นว่างไว้หรือป้อน 'us-east-1'" +objectStorageRegionDesc: "ระบุภูมิภาค เช่น ‘xx-east-1’ หากบริการของคุณไม่แยกภูมิภาค ให้ระบุเป็น ‘us-east-1’ หรือเว้นวางไว้หากใช้ AWS configuration files / environment variables" objectStorageUseSSL: "ใช้ SSL" objectStorageUseSSLDesc: "ปิดการทำงานนี้ไว้ ถ้าหากคุณจะไม่ใช้ HTTPS สำหรับการเชื่อมต่อ API" objectStorageUseProxy: "เชื่อมต่อผ่านพร็อกซี" objectStorageUseProxyDesc: "ปิดสิ่งนี้ไว้ถ้าหากคุณจะไม่ใช้ Proxy สำหรับการเชื่อมต่อ API" objectStorageSetPublicRead: "ตั้งค่าเป็น “public-read” เมื่ออัปโหลด" -s3ForcePathStyleDesc: "ถ้าหากเปิดใช้งาน s3ForcePathStyle ชื่อบัคเก็ตนั้นอาจจะต้องรวมอยู่ในเส้นทางของ URL ซึ่งตรงข้ามกับชื่อโฮสต์ของ URL คุณอาจจะต้องเปิดใช้งานการตั้งค่านี้เมื่อใช้บริการต่างๆ เช่น อินสแตนซ์ Minio ที่โฮสต์เองนะ" +s3ForcePathStyleDesc: "เมื่อเปิดใช้งาน s3ForcePathStyle จะบังคับให้ ระบุชื่อบัคเก็ตเป็นส่วนหนึ่งของพาธ แทนที่จะเป็นชื่อโฮสต์ใน URL, อาจจำเป็นต้องเปิดใช้งานตัวเลือกนี้เมื่อใช้กับ Minio ที่โฮสต์เองหรือบริการที่คล้ายกัน" serverLogs: "ปูมของเซิร์ฟเวอร์" deleteAll: "ลบทั้งหมด" showFixedPostForm: "แสดงแบบฟอร์มการโพสต์ที่ด้านบนสุดของไทม์ไลน์" @@ -575,7 +590,7 @@ sort: "เรียงลำดับ" ascendingOrder: "เรียงลำดับขึ้น" descendingOrder: "เรียงลำดับลง" scratchpad: "Scratchpad" -scratchpadDescription: "Scratchpad เป็นการจัดเตรียมสภาพแวดล้อมสำหรับการทดลอง AiScript แต่คุณสามารถเขียน ดำเนินการ และตรวจสอบผลลัพธ์ของการโต้ตอบกับ Misskey มันได้ด้วยนะ" +scratchpadDescription: "Scratchpad ให้สภาพแวดล้อมสำหรับการทดลอง AiScript คุณสามารถเขียนโค้ด/สั่งดำเนินการ/ตรวจสอบผลลัพธ์ ของการโต้ตอบกับ Misskey ได้" output: "เอาท์พุต" script: "สคริปต์" disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ" @@ -587,15 +602,15 @@ unsetUserBannerConfirm: "ต้องการเลิกตั้งแบน deleteAllFiles: "ลบไฟล์ทั้งหมด" deleteAllFilesConfirm: "ต้องการลบไฟล์ทั้งหมดใช่ไหม?" removeAllFollowing: "เลิกติดตามผู้ใช้ที่ติดตามทั้งหมด" -removeAllFollowingDescription: "เลิกติดตามทั้งหมดจาก {host} โปรดเรียกใช้สิ่งนี้เมื่ออินสแตนซ์ดังกล่าวได้สูญหายตายจากไปแล้ว" +removeAllFollowingDescription: "จะเลิกติดตามทั้งหมดจาก {host} โปรดดำเนินการสิ่งนี้เมื่อเซิร์ฟเวอร์ดังกล่าวได้สูญหายตายจากไปแล้ว" userSuspended: "ผู้ใช้รายนี้ถูกระงับการใช้งาน" userSilenced: "ผู้ใช้รายนี้ถูกปิดปากอยู่" yourAccountSuspendedTitle: "บัญชีนี้นั้นถูกระงับ" yourAccountSuspendedDescription: "บัญชีนี้ถูกระงับ เนื่องจากละเมิดข้อกำหนดในการให้บริการของเซิร์ฟเวอร์หรืออาจจะละเมิดหลักเกณฑ์ชุมชน หรือ อาจจะโดนร้องเรียนเรื่องการละเมิดลิขสิทธิ์และอื่นๆอย่างต่อเนื่องซ้ำๆ หากคุณคิดว่าไม่ได้ทำผิดจริงๆหรือตัดสินผิดพลาด ได้โปรดกรุณาติดต่อผู้ดูแลระบบหากคุณต้องการทราบเหตุผลโดยละเอียดเพิ่มเติม และขอความกรุณาอย่าสร้างบัญชีใหม่" tokenRevoked: "โทเค็นไม่ถูกต้อง" -tokenRevokedDescription: "โทเค็นนี้หมดอายุแล้วนะค่ะกรุณาเข้าสู่ระบบอีกครั้งนะ" +tokenRevokedDescription: "โทเค็นการเข้าสู่ระบบหมดอายุ กรุณาเข้าสู่ระบบใหม่อีกครั้ง" accountDeleted: "ลบบัญชีแล้ว" -accountDeletedDescription: "บัญชีนี้ถูกลบไปแล้วนะ" +accountDeletedDescription: "บัญชีนี้ถูกลบแล้ว" menu: "เมนู" divider: "ตัวแบ่ง" addItem: "เพิ่มรายการ" @@ -615,14 +630,14 @@ enablePlayer: "เปิดเครื่องเล่นวิดีโอ" disablePlayer: "ปิดเครื่องเล่นวิดีโอ" expandTweet: "ขยายทวีต" themeEditor: "ตัวแก้ไขธีม" -description: "รายละเอียด" +description: "คำอธิบาย" describeFile: "เพิ่มแคปชั่น" enterFileDescription: "ใส่แคปชั่น" author: "ผู้เขียน" leaveConfirm: "มีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ต้องการละทิ้งมันใช่ไหม?" manage: "การจัดการ" plugins: "ปลั๊กอิน" -preferencesBackups: "ตั้งค่าการสำรองข้อมูล" +preferencesBackups: "สำรองการตั้งค่า" deck: "เด็ค" undeck: "ออกจากเด็ค" useBlurEffectForModal: "ใช้เอฟเฟกต์เบลอสำหรับโมดอล" @@ -632,21 +647,21 @@ height: "ความสูง" large: "ใหญ่" medium: "ปานกลาง" small: "เล็ก" -generateAccessToken: "สร้างการเข้าถึงโทเค็น" -permission: "การอนุญาต" +generateAccessToken: "สร้างโทเค็นการเข้าถึง" +permission: "สิทธิ์" adminPermission: "สิทธิ์ของผู้ดูแลระบบ" enableAll: "เปิดใช้งานทั้งหมด" disableAll: "ปิดการใช้งานทั้งหมด" tokenRequested: "ให้สิทธิ์การเข้าถึงบัญชี" -pluginTokenRequestedDescription: "ปลั๊กอินนี้จะสามารถใช้การอนุญาตที่ตั้งค่าไว้ที่นี่นะ" +pluginTokenRequestedDescription: "ปลั๊กอินนี้จะใช้สิทธิ์ตามที่ตั้งค่าไว้ที่นี่" notificationType: "ประเภทการแจ้งเตือน" edit: "แก้ไข" -emailServer: "อีเมลเซิร์ฟเวอร์" +emailServer: "เซิร์ฟเวอร์ของอีเมล" enableEmail: "เปิดใช้งานการกระจายอีเมล" -emailConfigInfo: "ใช้เพื่อยืนยันอีเมลของคุณระหว่างการสมัครหรือถ้าหากคุณลืมรหัสผ่าน" +emailConfigInfo: "ใช้สำหรับการยืนยันอีเมลหรือการรีเซ็ตรหัสผ่าน" email: "อีเมล" emailAddress: "ที่อยู่อีเมล" -smtpConfig: "กำหนดค่าเซิร์ฟเวอร์ SMTP" +smtpConfig: "ตั้งค่าเซิร์ฟเวอร์ SMTP" smtpHost: "โฮสต์" smtpPort: "พอร์ต" smtpUser: "ชื่อผู้ใช้" @@ -656,10 +671,10 @@ smtpSecure: "ใช้โดยนัย SSL/TLS สำหรับการเ smtpSecureInfo: "ปิดสิ่งนี้เมื่อใช้ STARTTLS" testEmail: "ทดสอบการส่งอีเมล" wordMute: "ปิดเสียงคำ" -hardWordMute: "ปิดเสียงคำยาก" -regexpError: "ข้อผิดพลาดของนิพจน์ทั่วไป" -regexpErrorDescription: "เกิดข้อผิดพลาดในนิพจน์ทั่วไปในบรรทัดที่ {line} ของการปิดเสียงคำ {tab} ของคุณ:" -instanceMute: "ปิดเสียง อินสแตนซ์" +hardWordMute: "ปิดเสียงคำแบบแข็งโป๊ก" +regexpError: "เกิดข้อผิดพลาดใน regular expression" +regexpErrorDescription: "เกิดข้อผิดพลาดใน regular expression บรรทัดที่ {line} ของการปิดเสียงคำ {tab} :" +instanceMute: "ปิดเสียงเซิร์ฟเวอร์" userSaysSomething: "{name} พูดอะไรบางอย่าง" makeActive: "เปิดใช้งาน" display: "แสดงผล" @@ -690,17 +705,14 @@ reportAbuseOf: "รายงาน {name}" fillAbuseReportDescription: "กรุณากรอกรายละเอียดเกี่ยวกับรายงานนี้ หากเป็นเรื่องเกี่ยวกับโน้ตโดยเฉพาะ ได้โปรดระบุ URL" abuseReported: "เราได้ส่งรายงานของคุณไปแล้ว ขอบคุณมากๆนะ" reporter: "ผู้รายงาน" -reporteeOrigin: "รายงานต้นทาง" +reporteeOrigin: "ปลายทางรายงาน" reporterOrigin: "แหล่งผู้รายงาน" -forwardReport: "ส่งต่อรายงานไปยังอินสแตนซ์ระยะไกล" -forwardReportIsAnonymous: "ข้อมูลของคุณจะไม่ปรากฏบนอินสแตนซ์ระยะไกลและปรากฏเป็นบัญชีระบบที่ไม่ระบุชื่อ" send: "ส่ง" -abuseMarkAsResolved: "ทำเครื่องหมายรายงานว่าแก้ไขแล้ว" openInNewTab: "เปิดในแท็บใหม่" openInSideView: "เปิดในมุมมองด้านข้าง" defaultNavigationBehaviour: "พฤติกรรมการนำทางที่เป็นค่าเริ่มต้น" editTheseSettingsMayBreakAccount: "การแก้ไขการตั้งค่าเหล่านี้อาจทำให้บัญชีของคุณเสียหายนะ" -instanceTicker: "ข้อมูลอินสแตนซ์ของโน้ต" +instanceTicker: "ข้อมูลเซิร์ฟเวอร์ของโน้ต" waitingFor: "กำลังรอ {x}" random: "สุ่มค่า" system: "ระบบ" @@ -739,7 +751,7 @@ alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเ loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ" disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว" highlightSensitiveMedia: "ไฮไลท์สื่อที่มีเนื้อหาละเอียดอ่อน" -verificationEmailSent: "ส่งอีเมลยืนยันแล้วนะ ได้โปรดกรุณาไปที่ลิงก์ที่รวมไว้เพื่อทำการตรวจสอบให้เสร็จสิ้น" +verificationEmailSent: "ได้ส่งอีเมลยืนยันแล้ว กรุณาเข้าลิงก์ที่ระบุในอีเมลเพื่อทำการตั้งค่าให้เสร็จสิ้น" notSet: "ไม่ได้ตั้งค่า" emailVerified: "อีเมลได้รับการยืนยันแล้ว" noteFavoritesCount: "จำนวนโน้ตที่ชื่นชอบ" @@ -750,7 +762,7 @@ useSystemFont: "ใช้ฟอนต์เริ่มต้นของระ clips: "คลิป" experimentalFeatures: "ฟังก์ชั่นทดสอบ" experimental: "ทดลอง" -thisIsExperimentalFeature: "นี่คือฟีเจอร์ทดลองนะค่ะ ฟังก์ชันการทำงานบางอย่างอาจเปลี่ยนแปลงได้ และอาจไม่ทำงานหรือไม่เสถียรตามที่ตั้งใจไว้นะ" +thisIsExperimentalFeature: "นี่เป็นฟีเจอร์ทดลอง ซึ่งอาจมีการเปลี่ยนแปลงการทำงาน และอาจไม่ทำงานตามที่ตั้งใจไว้" developer: "สำหรับนักพัฒนา" makeExplorable: "ทำให้บัญชีมองเห็นใน “สำรวจ”" makeExplorableDescription: "ถ้าหากคุณปิดการทำงานนี้ บัญชีของคุณนั้นจะไม่แสดงในส่วน “สำรวจ”" @@ -761,14 +773,14 @@ center: "กึ่งกลาง" wide: "กว้าง" narrow: "ชิด" reloadToApplySetting: "การตั้งค่านี้จะมีผลหลังจากโหลดหน้าซ้ำเท่านั้น ต้องการที่จะโหลดใหม่เลยไหม?" -needReloadToApply: "จำเป็นต้องโหลดซ้ำถึงจะมีผลนะ" +needReloadToApply: "ต้องรีโหลดเพื่อให้การเปลี่ยนแปลงมีผล" showTitlebar: "แสดงแถบชื่อ" clearCache: "ล้างแคช" -onlineUsersCount: "{n} ผู้ใช้คนนี้กำลังออนไลน์" +onlineUsersCount: "{n} รายกำลังออนไลน์" nUsers: "{n} ผู้ใช้งาน" nNotes: "{n} โน้ต" -sendErrorReports: "ส่งรายงานว่าข้อผิดพลาด" -sendErrorReportsDescription: "เมื่อเปิดใช้งาน ข้อมูลข้อผิดพลาดโดยรายละเอียดนั้นจะถูกแชร์ให้กับ Misskey เมื่อเกิดปัญหา ซึ่งช่วยปรับปรุงคุณภาพของ Misskey\nซึ่งจะรวมถึงข้อมูล เช่น เวอร์ชั่นของระบบปฏิบัติการ เบราว์เซอร์ที่คุณใช้ กิจกรรมของคุณใน Misskey เป็นต้น" +sendErrorReports: "ส่งรายงานข้อผิดพลาด" +sendErrorReportsDescription: "เมื่อเปิดใช้งาน การแจ้งข้อผิดพลาดจะถูกแชร์กับ Misskey เมื่อเกิดปัญหา ซึ่งช่วยในการปรับปรุงคุณภาพของซอฟต์แวร์ ข้อมูลข้อผิดพลาดอาจรวมถึงเวอร์ชันของระบบปฏิบัติการ ประเภทของเบราว์เซอร์ และประวัติการใช้งาน ฯลฯ" myTheme: "ธีมของฉัน" backgroundColor: "สีพื้นหลัง" accentColor: "สีหลัก" @@ -780,7 +792,7 @@ value: "ค่า" createdAt: "สร้างเมื่อ" updatedAt: "อัปเดตล่าสุด" saveConfirm: "บันทึกเปลี่ยนแปลงมั้ย?" -deleteConfirm: "ลบจริงๆเหรอ?" +deleteConfirm: "ต้องการลบใช่ไหม?" invalidValue: "ค่านี้ไม่ถูกต้อง" registry: "ทะเบียน" closeAccount: "ปิด บัญชี" @@ -793,7 +805,7 @@ capacity: "ความจุ" inUse: "ใช้แล้ว" editCode: "แก้ไขโค้ด" apply: "นำไปใช้" -receiveAnnouncementFromInstance: "รับการแจ้งเตือนจากอินสแตนซ์นี้" +receiveAnnouncementFromInstance: "รับการแจ้งเตือนจากเซิร์ฟเวอร์นี้" emailNotification: "การแจ้งเตือนทางอีเมล" publish: "เผยแพร่" inChannelSearch: "ค้นหาในช่อง" @@ -821,7 +833,7 @@ active: "ใช้งานอยู่" offline: "ออฟไลน์" notRecommended: "ไม่แนะนำ" botProtection: "การป้องกัน Bot" -instanceBlocking: "อินสแตนซ์ที่ถูกบล็อก" +instanceBlocking: "เซิร์ฟเวอร์ที่ถูกบล็อก/ปิดปาก" selectAccount: "เลือกบัญชี" switchAccount: "สลับบัญชีผู้ใช้" enabled: "เปิดใช้งาน" @@ -831,9 +843,10 @@ user: "ผู้ใช้" administration: "การจัดการ" accounts: "บัญชีผู้ใช้" switch: "สลับ" -noMaintainerInformationWarning: "ข้อมูลผู้ดูแลไม่ได้รับการกำหนดค่านะ" -noBotProtectionWarning: "ไม่ได้กำหนดค่าการป้องกันบอทนะ" -configure: "กำหนดค่า" +noMaintainerInformationWarning: "ยังไม่ได้ตั้งค่าข้อมูลของผู้ดูแลระบบ" +noInquiryUrlWarning: "ยังไม่ได้ตั้งค่า URL สำหรับการติดต่อสอบถาม" +noBotProtectionWarning: "ยังไม่ได้ตั้งค่าการป้องกันบอต" +configure: "ตั้งค่า" postToGallery: "สร้างโพสต์แกลเลอรี่ใหม่" postToHashtag: "โพสต์ไปที่แฮชแท็กนี้" gallery: "แกลเลอรี่" @@ -870,7 +883,7 @@ accountDeletionInProgress: "กำลังดำเนินการลบบ usernameInfo: "ชื่อที่ระบุบัญชีของคุณจากผู้อื่นในเซิร์ฟเวอร์นี้ คุณสามารถใช้ตัวอักษร (a~z, A~Z), ตัวเลข (0~9) หรือขีดล่าง (_) ชื่อผู้ใช้ไม่สามารถเปลี่ยนแปลงได้ในภายหลัง" aiChanMode: "โหมด Ai " devMode: "โหมดนักพัฒนา" -keepCw: "เก็บคำเตือนเนื้อหา" +keepCw: "คงการเตือนเนื้อหาไว้" pubSub: "บัญชี Pub/Sub" lastCommunication: "การสื่อสารครั้งสุดท้ายล่าสุด" resolved: "คลี่คลายแล้ว" @@ -909,8 +922,8 @@ themeColor: "สีธีม" size: "ขนาด" numberOfColumn: "จำนวนคอลัมน์" searchByGoogle: "ค้นหา" -instanceDefaultLightTheme: "ธีมสว่างตามค่าเริ่มต้นของอินสแตนซ์" -instanceDefaultDarkTheme: "ธีมมืดตามค่าเริ่มต้นของอินสแตนซ์" +instanceDefaultLightTheme: "ธีมสว่างตามค่าเริ่มต้นของเซิร์ฟเวอร์" +instanceDefaultDarkTheme: "ธีมมืดตามค่าเริ่มต้นของเซิร์ฟเวอร์" instanceDefaultThemeDescription: "ป้อนรหัสธีมในรูปแบบออบเจ็กต์" mutePeriod: "ระยะเวลาปิดเสียง" period: "ระยะเวลา" @@ -930,7 +943,7 @@ cropNo: "ใช้ตามที่เป็นอยู่" file: "ไฟล์" recentNHours: "ล่าสุด {n} ชั่วโมงที่แล้ว" recentNDays: "ล่าสุด {n} วันที่แล้ว" -noEmailServerWarning: "ไม่ได้กำหนดค่าเซิร์ฟเวอร์อีเมลนี้" +noEmailServerWarning: "ยังไม่ได้ตั้งค่าเซิร์ฟเวอร์ของอีเมล" thereIsUnresolvedAbuseReportWarning: "มีรายงานที่ยังไม่ได้แก้ไข" recommended: "แนะนำ" check: "ตรวจสอบ" @@ -965,7 +978,7 @@ cannotUploadBecauseExceedsFileSizeLimit: "ไม่สามารถอัป beta: "เบต้า" enableAutoSensitive: "ทำเครื่องหมายว่ามีเนื้อหาที่ละเอียดอ่อนโดยอัตโนมัติ" enableAutoSensitiveDescription: "อนุญาตให้ตรวจหาและทำเครื่องหมายสื่อว่ามีเนื้อหาโดยละเอียดอ่อนโดยอัตโนมัติ ผ่าน Machine Learning หากเป็นไปได้ แม้ว่าคุณจะปิดคุณสมบัตินี้ ก็อาจถูกตั้งค่าโดยอัตโนมัติ ทั้งนี้ขึ้นอยู่กับเซิร์ฟเวอร์" -activeEmailValidationDescription: "เปิดใช้งานการตรวจสอบที่อยู่อีเมลให้มีความเข้มงวดยิ่งขึ้น ซึ่งอาจจะรวมไปถึงการตรวจสอบที่อยู่อีเมล์ที่ใช้แล้วทิ้งและโดยให้พิจารณาว่าสามารถสื่อสารด้วยได้หรือไม่ เมื่อไม่เลือกระบบจะตรวจสอบเฉพาะรูปแบบของอีเมลเท่านั้น" +activeEmailValidationDescription: "การตรวจสอบอีเมลของผู้ใช้จะเข้มงวดมากขึ้น โดยพิจารณาว่าเป็นอีเมลชั่วคราวหรือไม่ และสามารถติดต่อได้จริงหรือไม่ หากปิดการตรวจสอบนี้ จะตรวจสอบเพียงว่ารูปแบบอีเมลที่ถูกต้องหรือไม่เท่านั้น" navbar: "แถบนำทาง" shuffle: "สลับ" account: "บัญชีผู้ใช้" @@ -974,7 +987,7 @@ pushNotification: "การแจ้งเตือนแบบพุช" subscribePushNotification: "เปิดการแจ้งเตือนแบบพุช" unsubscribePushNotification: "ปิดการแจ้งเตือนแบบพุช" pushNotificationAlreadySubscribed: "การแจ้งเตือนแบบพุชได้เปิดใช้งานแล้ว" -pushNotificationNotSupported: "เบราว์เซอร์หรืออินสแตนซ์ของคุณนั้นไม่รองรับการแจ้งเตือนแบบพุช" +pushNotificationNotSupported: "เบราว์เซอร์หรือเซิร์ฟเวอร์ไม่รองรับการแจ้งเตือนแบบพุช" sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว" sendPushNotificationReadMessageCaption: "อาจทำให้อุปกรณ์ของคุณใช้พลังงานมากขึ้น" windowMaximize: "ขยายใหญ่สุด" @@ -1017,36 +1030,37 @@ achievements: "ความสำเร็จ" gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง" gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ" thisPostMayBeAnnoying: "โน้ตนี้อาจจะเป็นการรบกวนผู้อื่นนะคะ" -thisPostMayBeAnnoyingHome: "โพสต์ไปยังไทม์ไลน์หน้าแรก" -thisPostMayBeAnnoyingCancel: "เลิก" -thisPostMayBeAnnoyingIgnore: "โพสต์ยังไงก็แล้วแต่" +thisPostMayBeAnnoyingHome: "โพสต์ลงไทม์ไลน์หลักเท่านั้น" +thisPostMayBeAnnoyingCancel: "ยกเลิก" +thisPostMayBeAnnoyingIgnore: "โพสต์ไปเลย ไม่ต้องปรับการมองเห็น" collapseRenotes: "ยุบรีโน้ตที่คุณเคยเห็นแล้ว" +collapseRenotesDescription: "พับย่อโน้ตที่เคยตอบสนองหรือรีโน้ตแล้ว" internalServerError: "เซิร์ฟเวอร์ภายในเกิดข้อผิดพลาด" -internalServerErrorDescription: "เซิร์ฟเวอร์รันค้นพบข้อผิดพลาดที่ไม่คาดคิด" +internalServerErrorDescription: "เกิดข้อผิดพลาดที่ไม่คาดคิดภายในเซิร์ฟเวอร์" copyErrorInfo: "คัดลอกรายละเอียดข้อผิดพลาด" -joinThisServer: "ลงชื่อสมัครใช้ในอินสแตนซ์นี้" -exploreOtherServers: "มองหาอินสแตนซ์อื่น" +joinThisServer: "ลงทะเบียนในเซิร์ฟเวอร์นี้" +exploreOtherServers: "มองหาเซิร์ฟเวอร์อื่น" letsLookAtTimeline: "มาดูไทม์ไลน์กัน" -disableFederationConfirm: "ปิดใช้งานสหพันธ์จริงๆหรอแน่ใจแล้วนะ?" +disableFederationConfirm: "ปิดใช้งานสหพันธ์เลยใช่ไหม?" disableFederationConfirmWarn: "โพสต์จะยังคงเป็นสาธารณะต่อไป เว้นแต่จะตั้งค่าเป็นอย่างอื่น" disableFederationOk: "ปิดการใช้งาน" -invitationRequiredToRegister: "อินสแตนซ์นี้เป็นแบบรับเชิญ เฉพาะผู้ที่มีรหัสเชิญเท่านั้นที่สามารถลงทะเบียนได้" -emailNotSupported: "อินสแตนซ์นี้ไม่รองรับการส่งอีเมล" +invitationRequiredToRegister: "เซิร์ฟเวอร์นี้เป็นแบบรับเชิญ เฉพาะผู้มีรหัสเชิญเท่านั้นถึงสามารถลงทะเบียนได้" +emailNotSupported: "เซิร์ฟเวอร์นี้ไม่รองรับการส่งอีเมล" postToTheChannel: "โพสต์ลงช่อง" cannotBeChangedLater: "สิ่งนี้ไม่สามารถเปลี่ยนแปลงได้ในภายหลังนะ" reactionAcceptance: "การยอมรับรีแอคชั่น" likeOnly: "ที่ถูกใจเท่านั้น" -likeOnlyForRemote: "ทั้งหมด (เฉพาะการถูกใจจากอินสแตนซ์ระยะไกล)" +likeOnlyForRemote: "ทั้งหมด (เฉพาะการถูกใจจากเซิร์ฟเวอร์ระยะไกล)" nonSensitiveOnly: "เฉพาะไม่มีเนื้อหาละเอียดอ่อน" nonSensitiveOnlyForLocalLikeOnlyForRemote: "เฉพาะไม่มีเนื้อหาละเอียดอ่อน (เฉพาะการถูกใจจากระยะไกลเท่านั้น)" rolesAssignedToMe: "บทบาทที่ได้รับมอบหมายให้ฉัน" -resetPasswordConfirm: "รีเซ็ตรหัสผ่านของคุณจริงๆหรอ?" +resetPasswordConfirm: "ต้องการรีเซ็ตรหัสผ่านใช่ไหม?" sensitiveWords: "คำที่มีเนื้อหาละเอียดอ่อน" -sensitiveWordsDescription: "การเปิดเผยโน้ตทั้งหมดที่มีคำที่กำหนดค่าไว้จะถูกตั้งค่าเป็น \"หน้าแรก\" โดยอัตโนมัติ คุณยังสามารถแสดงหลายรายการได้โดยแยกรายการโดยใช้ตัวแบ่งบรรทัดได้นะ" -sensitiveWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ" +sensitiveWordsDescription: "โน้ตที่มีคำที่ระบุไว้จะถูกตั้งค่าการมองเห็นของให้แสดงเฉพาะในหน้าหลักเท่านั้น คั่นคำด้วยการขึ้นบรรทัดใหม่" +sensitiveWordsDescription2: "ถ้าแยกด้วยเว้นวรรคจะเป็นการระบุ AND และถ้าล้อมคำด้วยสแลช (/) จะเป็นการใช้ regular expression" prohibitedWords: "คำต้องห้าม" prohibitedWordsDescription: "จะแจ้งเตือนว่าเกิดข้อผิดพลาดเมื่อพยายามโพสต์โน้ตที่มีคำที่กำหนดไว้ สามารถตั้งได้หลายคำด้วยการขึ้นบรรทัดใหม่" -prohibitedWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ" +prohibitedWordsDescription2: "ถ้าแยกด้วยเว้นวรรคจะเป็นการระบุ AND และถ้าล้อมคำด้วยสแลช (/) จะเป็นการใช้ regular expression" hiddenTags: "แฮชแท็กที่ซ่อนอยู่" hiddenTagsDescription: "เลือกแท็กที่จะไม่แสดงในรายการเทรนด์ สามารถลงทะเบียนหลายแท็กได้โดยขึ้นบรรทัดใหม่" notesSearchNotAvailable: "การค้นหาโน้ตไม่พร้อมใช้งาน" @@ -1058,7 +1072,7 @@ retryAllQueuesNow: "ลองเรียกใช้คิวทั้งหม retryAllQueuesConfirmTitle: "ลองใหม่ทั้งหมดจริงๆหรอแน่ใจนะ?" retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการโหลดเซิร์ฟเวอร์ชั่วคราวนะ" enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล" -enableChartsForFederatedInstances: "สร้างแผนภูมิข้อมูลอินสแตนซ์ระยะไกล" +enableChartsForFederatedInstances: "สร้างแผนภูมิของเซิร์ฟเวอร์ระยะไกล" showClipButtonInNoteFooter: "เพิ่ม “คลิป” ไปยังเมนูสั่งการของโน้ต" reactionsDisplaySize: "ขนาดของรีแอคชั่น" limitWidthOfReaction: "จำกัดความกว้างสูงสุดของรีแอคชั่นและแสดงให้เล็กลง" @@ -1077,7 +1091,7 @@ addMemo: "เพิ่มเมโม" editMemo: "แก้ไขเมโม" reactionsList: "รายการรีแอคชั่น" renotesList: "รายการรีโน้ต" -notificationDisplay: "การแจ้งเตือน" +notificationDisplay: "การแสดงการแจ้งเตือน" leftTop: "บนซ้าย" rightTop: "บนขวา" leftBottom: "ล่างซ้าย" @@ -1087,13 +1101,15 @@ vertical: "แนวตั้ง" horizontal: "แนวนอน" position: "ตำแหน่ง" serverRules: "กฎของเซิร์ฟเวอร์" -pleaseConfirmBelowBeforeSignup: "โปรดยืนยันที่ด้านล่างก่อนสมัครใช้งาน" +pleaseConfirmBelowBeforeSignup: "หากต้องการลงทะเบียนในเซิร์ฟเวอร์นี้ คุณต้องตรวจสอบและยอมรับสิ่งต่อไปนี้" pleaseAgreeAllToContinue: "คุณต้องยอมรับทุกช่องตรงด้านบนเพื่อดำเนินการต่อค่ะ" continue: "ดำเนินการต่อ" preservedUsernames: "ชื่อผู้ใช้ที่สงวนไว้" preservedUsernamesDescription: "ระบุชื่อผู้ใช้ที่จะสงวนชื่อไว้ คั่นด้วยการขึ้นบรรทัดใหม่ ชื่อผู้ใช้ที่ระบุที่นี่จะไม่สามารถใช้งานได้อีกต่อไปเมื่อสร้างบัญชีใหม่ ยกเว้นเมื่อผู้ดูแลระบบสร้างบัญชี นอกจากนี้ บัญชีที่มีอยู่แล้วจะไม่ได้รับผลกระทบ" createNoteFromTheFile: "เรียบเรียงโน้ตจากไฟล์นี้" archive: "เก็บถาวร" +archived: "เก็บถาวรแล้ว" +unarchive: "เลิกการเก็บถาวร" channelArchiveConfirmTitle: "ต้องการเก็บถาวรเจ้า {name} ใช่ไหม?" channelArchiveConfirmDescription: "เมื่อเก็บถาวรแล้ว จะไม่ปรากฏในรายการช่องหรือผลการค้นหาอีกต่อไป และจะไม่สามารถโพสต์ใหม่ได้อีกต่อไป" thisChannelArchived: "ช่องนี้ถูกเก็บถาวรแล้วนะ" @@ -1104,6 +1120,9 @@ preventAiLearning: "ปฏิเสธการเรียนรู้ด้ว preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว" options: "ตัวเลือกบทบาท" specifyUser: "ผู้ใช้เฉพาะ" +lookupConfirm: "ต้องการเรียกดูข้อมูลใช่ไหม?" +openTagPageConfirm: "ต้องการเปิดหน้าแฮชแท็กใช่ไหม?" +specifyHost: "ระบุโฮสต์" failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้" update: "อัปเดต" rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้" @@ -1157,7 +1176,7 @@ notifyNotes: "แจ้งเตือนเกี่ยวกับโพสต unnotifyNotes: "หยุดการแจ้งเตือนเกี่ยวกับโน้ตใหม่" authentication: "การตรวจสอบสิทธิ์" authenticationRequiredToContinue: "กรุณายืนยันตัวตนทางอิเล็กทรอนิกส์เพื่อดำเนินการต่อ" -dateAndTime: "เวลาประทับ" +dateAndTime: "วันเวลา" showRenotes: "แสดงรีโน้ต" edited: "แก้ไขแล้ว" notificationRecieveConfig: "การตั้งค่าการแจ้งเตือน" @@ -1168,11 +1187,11 @@ showRepliesToOthersInTimeline: "แสดงการตอบกลับผู hideRepliesToOthersInTimeline: "ไม่แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์" showRepliesToOthersInTimelineAll: "รวมตอบกลับจากทุกคนที่คุณติดตามไว้ในไทม์ไลน์ของคุณ" hideRepliesToOthersInTimelineAll: "ซ่อนตอบกลับจากทุกคนที่คุณติดตามไปจากไทม์ไลน์ของคุณ" -confirmShowRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการแสดงการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?" -confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?" +confirmShowRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการแสดงการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ ใส่ลงไทม์ไลน์ใช่ไหม?" +confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ ไปจากไทม์ไลน์ใช่ไหม?" externalServices: "บริการภายนอก" sourceCode: "ซอร์สโค้ด" -sourceCodeIsNotYetProvided: "ซอร์สโค้ดยังไม่พร้อมใช้งาน โปรดติดต่อผู้ดูแลระบบของคุณเพื่อแก้ไขปัญหานี้" +sourceCodeIsNotYetProvided: "ซอร์สโค้ดยังไม่พร้อมใช้งาน โปรดติดต่อผู้ดูแลระบบเพื่อแก้ไขปัญหานี้" repositoryUrl: "URL ของ repository" repositoryUrlDescription: "หากมีที่เก็บซอร์สโค้ดที่เปิดเผยต่อสาธารณะ ให้ป้อน URL ที่เก็บซอร์สโค้ดนั้น แต่หากคุณใช้ Misskey ตามต้นฉบับ (ไม่มีการเปลี่ยนแปลงซอร์สโค้ด) ให้ป้อน https://github.com/misskey-dev/misskey" repositoryUrlOrTarballRequired: "หากคุณไม่มี repository สาธารณะ คุณจะต้องจัดเตรียม tarball แทน ดู .config/example.yml สำหรับรายละเอียด" @@ -1227,7 +1246,7 @@ surrender: "ยอมแพ้" gameRetry: "เริ่มเกมใหม่" notUsePleaseLeaveBlank: "หากไม่ได้ใช้กรุณาเว้นว่างไว้" useTotp: "ใช้รหัสผ่านแบบใช้ครั้งเดียว (TOTP)" -useBackupCode: "ใช้รหัสสำรอง" +useBackupCode: "ใช้รหัสแบ๊กอัป" launchApp: "เริ่มแอป" useNativeUIForVideoAudioPlayer: "ใช้ UI ของเบราว์เซอร์เพื่อเล่นวิดีโอ/เสียง" keepOriginalFilename: "คงชื่อไฟล์เดิมไว้" @@ -1235,13 +1254,23 @@ keepOriginalFilenameDescription: "หากปิดการตั้งค่ noDescription: "ไม่มีข้อความอธิบาย" alwaysConfirmFollow: "แสดงข้อความยืนยันเมื่อกดติดตาม" inquiry: "ติดต่อเรา" +tryAgain: "โปรดลองอีกครั้ง" +confirmWhenRevealingSensitiveMedia: "ตรวจสอบก่อนแสดงสื่อที่มีเนื้อหาละเอียดอ่อน" +sensitiveMediaRevealConfirm: "สื่อนี้มีเนื้อหาละเอียดอ่อน, ต้องการแสดงใช่ไหม?" +createdLists: "รายชื่อที่ถูกสร้าง" +createdAntennas: "เสาอากาศที่ถูกสร้าง" _delivery: - stop: "ถูกระงับ" + status: "สถานะการจัดส่ง" + stop: "ระงับการส่ง" + resume: "จัดส่งต่อ" _type: none: "กำลังเผยแพร่" + manuallySuspended: "หยุดชั่วคราวด้วยตนเอง" + goneSuspended: "เซิร์ฟเวอร์ถูกระงับเนื่องจากมีการลบเซิร์ฟเวอร์นี้" + autoSuspendedForNotResponding: "เซิร์ฟเวอร์ถูกระงับเนื่องจากไม่ตอบสนอง" _bubbleGame: howToPlay: "วิธีเล่น" - hold: "หยุดชั่วคราว" + hold: "ถือไว้" _score: score: "คะแนน" scoreYen: "จำนวนเงินที่ได้รับ" @@ -1255,27 +1284,27 @@ _bubbleGame: section2: "เมื่อวัตถุประเภทเดียวกันมารวมกัน พวกมันจะกลายเป็นวัตถุใหม่และคุณจะได้รับคะแนน" section3: "หากวัตถุล้นออกมาจากกล่อง เกมก็จะจบลง ตั้งเป้าทำคะแนนให้สูงด้วยการหลอมวัตถุต่าง ๆ โดยไม่ทำให้ล้นกล่อง!" _announcement: - forExistingUsers: "ผู้ใช้งานที่มีอยู่เท่านั้น" - forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน" + forExistingUsers: "ผู้ใช้งานที่มีอยู่ตอนนี้เท่านั้น" + forExistingUsersDescription: "หากเปิดใช้งาน การประกาศนี้จะแสดงเฉพาะกับผู้ใช้ที่สร้างบัญชีก่อน/ที่มีอยู่ในขณะที่สร้างประกาศนี้เท่านั้น หากปิดใช้งาน การประกาศนี้จะแสดงกับผู้ใช้ที่สร้างบัญชีหลังจากสร้างประกาศนี้ด้วย" needConfirmationToRead: "จำเป็นต้องยืนยันว่าอ่านแล้ว" needConfirmationToReadDescription: "กล่องโต้ตอบการยืนยันจะปรากฏขึ้นเมื่อจะทำเครื่องหมายว่าอ่านแล้ว นอกจากนี้ยังทำให้ประกาศนี้ยังไม่ถูกอ่านเมื่อใช้ฟังก์ชั่น “ทำเครื่องหมายฯ ทั้งหมดว่าอ่านแล้ว”" end: "เก็บประกาศ" - tooManyActiveAnnouncementDescription: "การมีประกาศที่ใช้งานมากเกินไปนั้นอาจจะทำให้ประสบการณ์ของผู้ใช้งานนั้นดูแย่ลง โปรดกรุณาพิจารณาการเก็บประกาศที่ล้าสมัยด้วยนะค่ะ" + tooManyActiveAnnouncementDescription: "เนื่องจากมีการประกาศที่ยังใช้งานอยู่จำนวนมาก อาจทำให้ UX ลดลง แนะนำให้พิจารณาการเก็บประกาศที่สิ้นสุดไปแล้ว" readConfirmTitle: "ทำเครื่องหมายว่าอ่านแล้วเลยไหม?" readConfirmText: "จะทำเครื่องหมายใส่ “{title}” ว่าอ่านแล้ว" - shouldNotBeUsedToPresentPermanentInfo: "เราขอแนะนำให้ใช้ประกาศเพื่อโพสต์ข้อมูลแบบ flow มากกว่าข้อมูลแบบ stock เนื่องจากมีแนวโน้มที่จะส่งผลเสียต่อ UX โดยเฉพาะสำหรับผู้ใช้ใหม่" + shouldNotBeUsedToPresentPermanentInfo: "เนื่องจากมีความเป็นไปได้สูงที่จะส่งผลเสียต่อง UX ของผู้ใช้ใหม่ จึงขอแนะนำให้ใช้ประกาศสำหรับข้อมูลที่ต้องการการตอบสนองในทันที ไม่ใช่ข้อมูลที่ต้องการแสดงตลอดเวลา" dialogAnnouncementUxWarn: "เราขอแนะนำให้ใช้ด้วยความระมัดระวัง เนื่องจากการแจ้งเตือนแบบกล่องโต้ตอบตั้งแต่ 2 รายการขึ้นไปพร้อมกันอาจส่งผลเสียต่อ UX ได้อย่างมาก" silence: "ไม่มีการแจ้งเตือน" silenceDescription: "หากเปิดใช้งาน จะไม่มีการแจ้งเตือนประกาศนี้ และผู้ใช้จะไม่จำเป็นต้องทำเครื่องหมายว่าอ่านแล้ว" _initialAccountSetting: - accountCreated: "คุณได้สร้างบัญชีของคุณสำเร็จเรียบร้อยแล้ว!" + accountCreated: "สร้างบัญชีเสร็จสมบูรณ์!" letsStartAccountSetup: "สำหรับผู้เริ่มต้นมาตั้งค่าโปรไฟล์ของคุณกันเถอะ" letsFillYourProfile: "ก่อนอื่นมาตั้งค่าโปรไฟล์ของคุณ" profileSetting: "ตั้งค่าโปรไฟล์" privacySetting: "ตั้งค่าความเป็นส่วนตัว" theseSettingsCanEditLater: "คุณสามารถเปลี่ยนการตั้งค่าเหล่านี้ได้ในภายหลังได้ตลอดเวลานะ" - youCanEditMoreSettingsInSettingsPageLater: "ยังมีการตั้งค่าอื่นๆ อีกมากมายที่คุณนั้นสามารถกำหนดค่าได้จาก \"การตั้งค่า\" เพื่อให้แน่ใจว่าได้เยี่ยมชมมันได้ภายหลังนะ" - followUsers: "ลองติดตามผู้ใช้บางคนที่คุณอาจจะสนใจเพื่อสร้างไทม์ไลน์ของคุณสิ !" + youCanEditMoreSettingsInSettingsPageLater: "สามารถตั้งค่าเพิ่มเติมได้ที่หน้า “การตั้งค่า” อย่าลืมไปเยี่ยมชมภายหลังด้วย" + followUsers: "ลองติดตามผู้ใช้ที่สนใจเพื่อสร้างไทม์ไลน์ดูสิ" pushNotificationDescription: "กำลังเปิดใช้งานการแจ้งเตือนแบบพุชจะช่วยให้คุณได้รับการแจ้งเตือนจาก {name} โดยตรงบนอุปกรณ์ของคุณนะ" initialAccountSettingCompleted: "ตั้งค่าโปรไฟล์เสร็จสมบูรณ์แล้ว!" haveFun: "ขอให้สนุกกับ {name}!" @@ -1310,7 +1339,7 @@ _initialTutorial: description1: "Misskey มีหลายไทม์ไลน์ขึ้นอยู่กับวิธีการใช้งานของคุณ (บางไทม์ไลน์อาจไม่สามารถใช้ได้ขึ้นอยู่กับนโยบายของเซิร์ฟเวอร์)" home: "คุณสามารถดูโพสต์จากบัญชีที่คุณติดตามได้" local: "คุณสามารถดูโพสต์จากผู้ใช้ทั้งหมดบนเซิร์ฟเวอร์นี้" - social: "โพสต์จากทั้งไทม์ไลน์หน้าแรกและไทม์ไลน์ในพื้นที่ของคุณจะปรากฏขึ้น" + social: "จะแสดงโพสต์ทั้งจากไทม์ไลน์หลักและไทม์ไลน์ท้องถิ่น" global: "คุณสามารถดูโพสต์จากเซิร์ฟเวอร์ที่เชื่อมต่ออื่นๆ ทั้งหมดได้" description2: "คุณสามารถสลับระหว่างแต่ละไทม์ไลน์ได้ตลอดเวลาได้ที่บริเวณด้านบนของหน้าจอ" description3: "นอกจากนี้ยังมีรายการไทม์ไลน์ ไทม์ไลน์ของช่อง ฯลฯ โปรดดู {link} สำหรับรายละเอียดเพิ่มเติม" @@ -1320,7 +1349,7 @@ _initialTutorial: _visibility: description: "คุณสามารถจำกัดผู้ที่สามารถดูโน้ตของคุณได้นะ" public: "โน้ตของคุณนั้นจะปรากฏแก่ผู้ใช้งานทุกคน" - home: "เผยแพร่บนไทม์ไลน์หน้าแรกเท่านั้น ผู้คนที่เข้าชมโปรไฟล์ของคุณ ผ่านผู้ติดตาม และผ่านการรีโน้ตสามารถเห็นได้" + home: "เผยแพร่บนไทม์ไลน์หลักเท่านั้น แต่ผู้ติดตาม ผู้ที่เข้ามาดูโปรไฟล์ และผู้ที่เห็นจากรีโน้ตยังสามารถดูโพสต์นี้ได้" followers: "มองเห็นได้เฉพาะผู้ติดตามเท่านั้น ไม่มีใครอื่นนอกจากตัวคุณเองที่สามารถรีโน้ตได้ และมีเพียงผู้ติดตามของคุณเท่านั้นที่สามารถดูได้" direct: "เปิดให้เห็นเฉพาะผู้ใช้ที่ระบุเท่านั้น และพวกเขาจะได้รับแจ้งเตือนด้วย คุณสามารถใช้มันแทนข้อความโดยตรง (dm)" doNotSendConfidencialOnDirect1: "โปรดใช้ความระมัดระวังในการส่งข้อมูลที่ละเอียดอ่อน" @@ -1328,9 +1357,9 @@ _initialTutorial: localOnly: "การโพสต์ด้วย flag นี้จะไม่รวมโน้ตไปยังเซิร์ฟเวอร์อื่น ผู้ใช้บนเซิร์ฟเวอร์อื่นจะไม่สามารถดูโน้ตเหล่านี้ได้โดยตรง โดยไม่คำนึงถึงการตั้งค่าการแสดงผลข้างต้น" _cw: title: "คำเตือนเกี่ยวกับเนื้อหา" - description: "เนื้อหาที่เขียนด้วย “คำอธิบายประกอบ” จะแสดงแทนข้อความหลัก คลิก “ดูเพิ่มเติม” เพื่อแสดงข้อความเต็ม" + description: "เนื้อหาที่เขียนใน “คำอธิบายประกอบ” จะแสดงแทนเนื้อหาหลัก ต้องคลิก “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง" _exampleNote: - cw: "นี่อาจจะทำให้คุณหิวอย่างแน่นอน!" + cw: " ห้ามดู ระวังหิว" note: "เพิ่งไปกินโดนัทเคลือบช็อคโกแลตมา 🍩😋" useCases: "ใช้สิ่งนี้เพื่อระบุโน้ตที่ต้องตามแนวทางปฏิบัติของเซิร์ฟเวอร์ หรือเพื่อควบคุมการสปอยล์และข้อความที่ละเอียดอ่อนด้วยตนเอง" _howToMakeAttachmentsSensitive: @@ -1346,17 +1375,17 @@ _initialTutorial: title: "บทเรียนจบลงแล้วจ้า เย่เย่เย่ 🎉" description: "คุณสมบัติที่แนะนำในที่นี่เป็นเพียงบางส่วนเท่านั้น หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีใช้ Misskey โปรดไปที่ {link}" _timelineDescription: - home: "บนไทม์ไลน์หน้าแรก คุณสามารถดูโพสต์จากบัญชีที่คุณติดตามได้" - local: "ไทม์ไลน์ในพื้นที่ช่วยให้คุณเห็นโพสต์จากผู้ใช้ทั้งหมดบนเซิร์ฟเวอร์นี้" - social: "ไทม์ไลน์โซเชียลจะแสดงโพสต์จากทั้งไทม์ไลน์หน้าแรกและไทม์ไลน์ในพื้นที่" + home: "บนไทม์ไลน์หลัก คุณสามารถดูโพสต์จากบัญชีที่ติดตามอยู่ได้" + local: "ไทม์ไลน์ท้องถิ่นช่วยให้เห็นโพสต์จากผู้ใช้ทั้งหมดบนเซิร์ฟเวอร์นี้" + social: "ไทม์ไลน์โซเชียลจะแสดงโพสต์จากทั้งไทม์ไลน์หลักและไทม์ไลน์ท้องถิ่น" global: "ในไทม์ไลน์ทั่วโลก คุณสามารถดูโน้ตจากเซิร์ฟเวอร์ที่เชื่อมต่อทั้งหมดได้" _serverRules: description: "ชุดของกฎที่จะแสดงก่อนการลงทะเบียนเราขอแนะนำให้ตั้งค่าสรุปข้อกำหนดในการให้บริการ" _serverSettings: iconUrl: "URL ไอคอน" appIconDescription: "ระบุไอคอนที่จะใช้เมื่อ {host} แสดงเป็นแอป" - appIconUsageExample: "E.g. เป็น PWA หรือเมื่อแสดงผลเป็นบุ๊กมาร์กหน้าจอหลักบนโทรศัพท์" - appIconStyleRecommendation: "เนื่องจากไอคอนอาจถูกครอบตัดเป็นสี่เหลี่ยมจัตุรัสหรือวงกลม จึงแนะนำให้ใช้ไอคอนที่มีขอบสีรอบๆ เนื้อหา" + appIconUsageExample: "ตัวอย่างเช่น เมื่อถูกเพิ่มเป็น PWA หรือบุ๊กมาร์กบนหน้าจอหลักในสมาร์ทโฟน" + appIconStyleRecommendation: "เนื่องจากอาจถูกครอบตัดเป็นสี่เหลี่ยมหรือวงกลม จึงแนะนำให้ใช้ภาพที่เผื่อพื้นที่รอบๆ ตัวโลโก้ไอคอนไว้" appIconResolutionMustBe: "ความละเอียดขั้นต่ำไว้คือ {resolution}." manifestJsonOverride: "เขียนทับ manifest.json" shortName: "ชื่อย่อ" @@ -1364,27 +1393,29 @@ _serverSettings: fanoutTimelineDescription: "เพิ่มประสิทธิภาพการดึงข้อมูลไทม์ไลน์อย่างมาก และลดภาระในฐานข้อมูลเมื่อเปิดใช้งาน ในทางกลับกัน การใช้หน่วยความจำของ Redis จะเพิ่มขึ้น ลองปิดการใช้งานนี้ในกรณีที่หน่วยความจำเซิร์ฟเวอร์เหลือน้อยหรือเซิร์ฟเวอร์ไม่เสถียร" fanoutTimelineDbFallback: "ฟอลแบ๊กกลับฐานข้อมูล" fanoutTimelineDbFallbackDescription: "เมื่อเปิดใช้งาน หากไม่ได้แคชไทม์ไลน์ ไทม์ไลน์จะฟอลแบ๊กไปยังฐานข้อมูลสำหรับการ query เพิ่มเติม การปิดใช้งานจะช่วยลดภาระของเซิร์ฟเวอร์ด้วยการกำจัดกระบวนฟอลแบ๊ก แต่มันก็จะจำกัดช่วงเวลาไทม์ไลน์ที่สามารถดึงข้อมูลได้" + inquiryUrl: "URL สำหรับการติดต่อสอบถาม" + inquiryUrlDescription: "ระบุ URL ของหน้าเว็บที่มีแบบฟอร์มสำหรับติดต่อผู้ดูแลเซิร์ฟเวอร์ หรือข้อมูลการติดต่อของผู้ดูแลเซิร์ฟเวอร์" _accountMigration: - moveFrom: "ย้ายข้อมูลบัญชีอื่นไปยังอีกบัญชีนี้หนึ่ง" + moveFrom: "ย้ายจากบัญชีอื่นมาที่บัญชีนี้" moveFromSub: "สร้างนามแฝงไปยังบัญชีอื่น" moveFromLabel: "บัญชีที่จะย้ายจาก #{n}" - moveFromDescription: "ถ้าหากคุณต้องการโอนข้อมูล คุณจำเป็นต้องสร้างบัญชีสำรองสำหรับการย้ายบัญชี หลังจากนั้นป้อนบัญชีที่จะย้ายไปในรูปแบบต่อไปนี้: @person@instance.com" - moveTo: "ย้ายข้อมูลบัญชีนี้ไปยังบัญชีอีกหนึ่ง" + moveFromDescription: "หากต้องการโอนข้อมูลจากบัญชีอื่นมายังบัญชีนี้ จำเป็นต้องสร้างบัญชีนามแฝง (alias) ไว้ที่นี่ด้วย\nกรุณากรอกบัญชีเดิมในรูปแบบ: @username@server.example.com\nหากต้องการลบ alias, ให้เว้นว่างไว้แล้วบันทึก (ไม่แนะนำ)" + moveTo: "ย้ายบัญชีนี้ไปยังบัญชีใหม่" moveToLabel: "บัญชีที่จะย้ายไปที่:" moveCannotBeUndone: "ไม่สามารถยกเลิกการโอนย้ายบัญชีได้" moveAccountDescription: "การดำเนินการนี้จะย้ายบัญชีของคุณไปยังบัญชีอื่น\n・ผู้ที่กำลังติดตามคุณจากบัญชีนี้จะถูกย้ายไปยังบัญชีใหม่โดยอัตโนมัติ\n・บัญชีนี้จะเลิกติดตามผู้ใช้ทั้งหมดที่กำลังติดตามอยู่\n・คุณจะไม่สามารถสร้างโน้ต ฯลฯ ในบัญชีนี้ได้\n\nแม้ว่าการย้ายผู้ที่ติดตามคุณจะเป็นไปโดยอัตโนมัติ แต่คุณต้องเตรียมขั้นตอนบางอย่างด้วยตนเอง เพื่อย้ายรายชื่อผู้ใช้ที่คุณกำลังติดตาม โดยดำเนินการส่งออกรายชื่อแล้วค่อยนำเข้ามาภายหลังในเมนูการตั้งค่าของบัญชีใหม่ ใช้ขั้นตอนเดียวกันนี้ใช้รายชื่อผู้ใช้ที่ถูกปิดเสียงและถูกบล็อก\n\n(คำอธิบายนี้ใช้กับ Misskey v13.12.0 ขึ้นไป, ซอฟต์แวร์ ActivityPub อื่นๆ เช่น Mastodon อาจทำงานแตกต่างออกไป)" - moveAccountHowTo: "หากต้องการย้ายข้อมูลก่อนอื่นให้สร้างชื่อแทนสำหรับบัญชีนี้ ในบัญชีที่จะต้องการย้ายไป\nหลังจากที่คุณสร้างนามแฝงนั้นแล้ว ให้ป้อนบัญชีที่ต้องการจะย้ายไปในรูปแบบดังต่อไปนี้: @username@server.example.com" + moveAccountHowTo: "การย้ายบัญชีจะเริ่มต้นโดยการสร้างบัญชีนามแฝง (alias) ของบัญชีนี้ ณ บัญชีที่เป็นปลายทาง หลังจากสร้างนามแฝงแล้ว ให้ป้อนบัญชีปลายทางในรูปแบบดังนี้: @username@server.example.com" startMigration: "โอนย้าย" migrationConfirm: "ยืนยันการย้ายข้อมูลบัญชีนี้ไปที่ {account} เมื่อเริ่มแล้วจะไม่สามารถหยุดหรือนำกลับคืนมาได้ และคุณจะไม่สามารถใช้บัญชีนี้ในสถานะดั้งเดิมได้อีกต่อไป\n\nนอกจากนี้ คุณจำเป็นต้องสร้างบัญชีสำรองสำหรับการย้ายบัญชี" - movedAndCannotBeUndone: "\nบัญชีนี้ถูกโอนย้ายไปแล้ว\nไม่สามารถย้อนกลับโอนย้ายข้อมูลได้" - postMigrationNote: "บัญชีนี้จะถูกเลิกติดตามบัญชีทั้งหมดที่กำลังติดตามภายใน 24 ชั่วโมงหลังจากการย้ายข้อมูลนั้นเสร็จสิ้น ทั้งจำนวนผู้ติดตามและผู้ติดตามนั้นจะกลายเป็นศูนย์ เพื่อหลีกเลี่ยงป้องกันไม่ให้ผู้ติดตามของคุณนั้นไม่สามารถเห็นโพสต์เฉพาะผู้ติดตามของบัญชีนี้ได้ แต่อย่างไรก็ตามแล้วพวกเขาจะยังคงติดตามบัญชีนี้ต่อไป" - movedTo: "บัญชีที่จะย้ายไปที่:" + movedAndCannotBeUndone: "\nบัญชีนี้ถูกโอนย้ายไปแล้ว\nไม่สามารถยกเลิกการโอนย้ายได้" + postMigrationNote: "บัญชีนี้จะดำเนินการยกเลิกการติดตามทั้งหมดหลังจากการย้ายข้อมูลไปแล้ว 24 ชั่วโมง จำนวนกำลังติดตามและจำนวนผู้ติดตามของบัญชีนี้จะเป็น 0 และเพื่อหลีกเลี่ยงไม่ให้ผู้ติดตามคุณนั้นไม่สามารถเห็นโพสต์เฉพาะผู้ติดตามฯได้ การยกเลิกการติดตามจะไม่กระทบกับผู้ติดตามคุณ ดังนั้นผู้ติดตามคุณยังคงสามารถดูโพสต์ของบัญชีนี้ได้" + movedTo: "บัญชีที่จะย้ายไป:" _achievements: earnedAt: "ได้รับเมื่อ" _types: _notes1: title: "just setting up my msky" - description: "โพสต์โน้ตแรกของคุณ" + description: "โพสต์โน้ตเป็นครั้งแรก" flavor: "ขอให้มีช่วงเวลาที่ดีกับ Misskey นะคะ!" _notes10: title: "โน้ตไม่กี่ชิ้น" @@ -1444,15 +1475,15 @@ _achievements: title: "มือใหม่ III" description: "เข้าสู่ระบบเป็นเวลารวม 15 วัน" _login30: - title: "มิสคิสท์ I" + title: "มิสคิสต์ I" description: "เข้าสู่ระบบเป็นเวลารวม 30 วัน" _login60: - title: "มิสคิสท์ II" + title: "มิสคิสต์ II" description: "เข้าสู่ระบบเป็นเวลารวม 60 วัน" _login100: - title: "มิสคิสท์ III" + title: "มิสคิสต์ III" description: "เข้าสู่ระบบเป็นเวลารวม 100 วัน" - flavor: "มิสคิสต์หัวรุนแรง" + flavor: "Violent Misskist (ทำไมเหมือนชื่อหนังสักเรื่องจังเลยนะ)" _login200: title: "ลูกค้าประจำ I" description: "เข้าสู่ระบบเป็นเวลารวม 200 วัน" @@ -1484,19 +1515,19 @@ _achievements: flavor: "ขอบคุณที่ใช้ Misskey นะ !" _noteClipped1: title: "อดไม่ได้ที่จะต้องคลิปมันเอาไว้" - description: "คลิปโน้ตตัวแรกของคุณ" + description: "คลิปโน้ตเป็นครั้งแรก" _noteFavorited1: title: "สตาร์เกเซอร์" - description: "ชื่นชอบโน้ตแรกของคุณ" + description: "ใส่โน้ตเป็นรายการโปรดเป็นครั้งแรก" _myNoteFavorited1: title: "แสวงหาดวงดาว" - description: "มีคนอื่นๆที่ชื่นชอบหนึ่งในโน้ตของคุณ" + description: "โน้ตตัวเองถูกคนอื่นเพิ่มลงรายการโปรดของเขา" _profileFilled: title: "เตรียมตัวอย่างดี" - description: "ตั้งค่าโปรไฟล์ของคุณ" + description: "ตั้งค่าโปรไฟล์" _markedAsCat: title: "ฉันเป็นแมว" - description: "ทำเครื่องหมายบัญชีของคุณว่าเป็นแมว" + description: "ตั้งค่าบัญชีเป็นแมวเมี้ยวเมี้ยว" flavor: "แมวน้อยไร้ชื่อ" _following1: title: "ก้าวแรกสู่...กดติดตาม" @@ -1539,7 +1570,7 @@ _achievements: description: "ได้รับความสำเร็จ 30 ครั้ง" _viewAchievements3min: title: "ชอบบรรลุความสําเร็จ" - description: "มองดูรายการความสำเร็จของคุณเป็นเวลาอย่างน้อย 3 นาที" + description: "มองดูรายการความสำเร็จเป็นเวลานานกว่า 3 นาที" _iLoveMisskey: title: "ฉันรัก Misskey" description: "โพสต์ “I ❤ #Misskey”" @@ -1566,13 +1597,13 @@ _achievements: flavor: "โป๊ะ โป๊ะ โป๊ะ ปิ้งงงงง" _selfQuote: title: "อ้างอิงตนเอง" - description: "อ้างโน้ตของคุณเอง" + description: "อ้างอิงโน้ตตัวเอง" _htl20npm: title: "ไทม์ไลน์ไหล" - description: "มีการทำความเร็วของไทม์ไลน์หน้าแรกเกิน 20 npm (โน้ตต่อนาที)" + description: "มีการทำความเร็วของไทม์ไลน์หลักเกิน 20 npm (โน้ตต่อนาที)" _viewInstanceChart: title: "วิเคราะห์" - description: "ดูแผนภูมิอินสแตนซ์ของคุณ" + description: "ดูแผนภูมิของเซิร์ฟเวอร์" _outputHelloWorldOnScratchpad: title: "หวัดดีชาวโลก!" description: "เอาพุต \"hello world\" ใน Scratchpad" @@ -1593,16 +1624,16 @@ _achievements: description: "มีโอกาสที่จะได้รับด้วยความน่าจะเป็นไปได้ 0.005% ทุก ๆ 10 วินาที" _setNameToSyuilo: title: "คอมเพล็กซ์ของพระเจ้า" - description: "ตั้งชื่อของคุณเป็น “syuilo”" + description: "ตั้งชื่อเป็น “syuilo”" _passedSinceAccountCreated1: title: "ครบรอบหนึ่งปี" - description: "ผ่านไปหนึ่งปีแล้วนะตั้งแต่บัญชีของคุณถูกสร้างขึ้นมาน่ะ" + description: "ผ่านไป 1 ปีนับตั้งแต่สร้างบัญชี" _passedSinceAccountCreated2: title: "ครบรอบสองปี" - description: "ผ่านไปสองปีแล้วนะตั้งแต่บัญชีของคุณถูกสร้างขึ้นมาน่ะ" + description: "ผ่านไป 2 ปีนับตั้งแต่สร้างบัญชี" _passedSinceAccountCreated3: title: "ครบรอบสามปี" - description: "ผ่านไปสามปีแล้วนะตั้งแต่บัญชีของคุณถูกสร้างขึ้นมาน่ะ" + description: "ผ่านไป 3 ปีนับตั้งแต่สร้างบัญชี" _loggedInOnBirthday: title: "สุขสันต์วันเกิด" description: "เข้าสู่ระบบในวันเกิดของคุณ" @@ -1637,7 +1668,7 @@ _role: name: "ชื่อบทบาท" description: "คำอธิบายบทบาท" permission: "สิทธิ์ตามบทบาท" - descriptionOfPermission: "ผู้ควบคุม สามารถดำเนินการดูแลขั้นพื้นฐานได้\nผู้ดูแลระบบ สามารถเปลี่ยนการตั้งค่าทั้งหมดของอินสแตนซ์ได้" + descriptionOfPermission: "ผู้ควบคุม สามารถดำเนินการดูแลขั้นพื้นฐานได้\nผู้ดูแลระบบ สามารถเปลี่ยนการตั้งค่าทั้งหมดของเซิร์ฟเวอร์ได้" assignTarget: "มอบหมาย" descriptionOfAssignTarget: "แบบปรับเอง เพิ่มถอนบทบาทนี้แก่ผู้ใช้ด้วยตัวเอง\nแบบมีเงื่อนไข เพิ่มถอนบทบาทนี้แก่ผู้ใช้โดยอัตโนมัติหากเข้าเงื่อนไขใดต่อไปนี้" manual: "ปรับเอง" @@ -1650,8 +1681,8 @@ _role: descriptionOfIsPublic: "บทบาทจะปรากฏบนโปรไฟล์ของผู้ใช้และเปิดเผยต่อสาธารณะ (ทุกคนสามารถเห็นได้ว่าผู้ใช้รายนี้มีบทบาทนี้)" options: "ตัวเลือกบทบาท" policies: "นโยบาย" - baseRole: "เทมเพลตบทบาท" - useBaseValue: "ใช้ตามเทมเพลตบทบาท" + baseRole: "แม่แบบบทบาท" + useBaseValue: "ใช้ตามแม่แบบบทบาท" chooseRoleToAssign: "เลือกบทบาทที่ต้องการกำหนด" iconUrl: "URL ไอคอน" asBadge: "แสดงเป็นตรา" @@ -1668,11 +1699,11 @@ _role: middle: "ปานกลาง" high: "สูง" _options: - gtlAvailable: "การดูไทม์ไลน์ทั่วโลก" - ltlAvailable: "การดูไทม์ไลน์ในท้องถิ่น" + gtlAvailable: "สามารถดูไทม์ไลน์ทั่วโลกได้" + ltlAvailable: "สามารถดูไทม์ไลน์ท้องถิ่นได้" canPublicNote: "สามารถโพสต์แบบสาธารณะ" mentionMax: "จำนวนการกล่าวถึงสูงสุดต่อโน้ต" - canInvite: "สร้างรหัสเชิญอินสแตนซ์" + canInvite: "สร้างรหัสเชิญเข้าเซิร์ฟเวอร์" inviteLimit: "จำกัดการเชิญ" inviteLimitCycle: "คูลดาวน์ในการเชิญ" inviteExpirationTime: "วันหมดอายุของรหัสการเชิญ" @@ -1680,6 +1711,7 @@ _role: canManageAvatarDecorations: "จัดการตกแต่งอวตาร" driveCapacity: "ความจุของไดรฟ์" alwaysMarkNsfw: "ทำเครื่องหมายไฟล์ว่าเป็น NSFW เสมอ" + canUpdateBioMedia: "อนุญาตให้ปรับปรุงไอคอนและแบนเนอร์" pinMax: "จํานวนสูงสุดของโน้ตที่ปักหมุดไว้" antennaMax: "จำนวนสูงสุดของเสาอากาศ" wordMuteMax: "จำนวนอักขระสูงสุดที่อนุญาตในการปิดเสียงคำ" @@ -1696,7 +1728,7 @@ _role: avatarDecorationLimit: "จำนวนการตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้" _condition: roleAssignedTo: "มอบหมายให้มีบทบาทแบบทำมือ" - isLocal: "ผู้ใช้ในพื้นที่" + isLocal: "ผู้ใช้ท้องถิ่น" isRemote: "ผู้ใช้ระยะไกล" isCat: "ผู้ใช้ที่เป็นแมว" isBot: "ผู้ใช้ที่เป็นบอต" @@ -1755,8 +1787,8 @@ _ad: adsTooClose: "เนื่องจากช่วงเวลาการแสดงโฆษณาสั้นมาก ประสบการณ์ผู้ใช้จึงอาจลดลงอย่างมาก" _forgotPassword: enterEmail: "ป้อนที่อยู่อีเมลที่คุณเคยใช้ในการลงทะเบียนไว้ ลิงก์ที่คุณสามารถรีเซ็ตรหัสผ่านได้นั้นจะถูกส่งไปนะ" - ifNoEmail: "ถ้าหากคุณไม่ได้ใช้อีเมลระหว่างการลงทะเบียน กรุณาติดต่อผู้ดูแลระบบอินสแตนซ์แทนนะ" - contactAdmin: "อินสแตนซ์นี้ไม่รองรับการใช้งานที่อยู่อีเมลนี้ กรุณาติดต่อผู้ดูแลระบบอินสแตนซ์เพื่อรีเซ็ตรหัสผ่านของคุณแทน" + ifNoEmail: "หากลงทะเบียนแบบไม่ใช้อีเมล โปรดติดต่อผู้ดูแลระบบ" + contactAdmin: "เนื่องจากเซิร์ฟเวอร์นี้ไม่รองรับการส่งอีเมล หากต้องการรีเซ็ตรหัสผ่าน กรุณาติดต่อผู้ดูแลระบบ" _gallery: my: "แกลลอรี่ของฉัน" liked: "โพสต์ที่ถูกใจ" @@ -1774,23 +1806,23 @@ _plugin: viewSource: "ดูต้นฉบับ" viewLog: "แสดงปูม" _preferencesBackups: - list: "สร้างการสำรองข้อมูล" - saveNew: "บันทึกข้อมูลสำรองใหม่" + list: "การตั้งค่าที่สำรองไว้" + saveNew: "บันทึกการตั้งค่าสำรองใหม่" loadFile: "โหลดจากไฟล์" apply: "นำไปใช้กับอุปกรณ์นี้" save: "บันทึก" - inputName: "กรุณาป้อนชื่อสำหรับข้อมูลสำรองนี้" + inputName: "กรุณาป้อนชื่อการตั้งค่าสำรองนี้" cannotSave: "การบันทึกล้มเหลว" - nameAlreadyExists: "มีข้อมูลสำรองชื่อ \"{name}\" นี้อยู่แล้ว กรุณาป้อนชื่ออื่นนะ" - applyConfirm: "คุณต้องการใช้ข้อมูลสำรอง \"{name}\" กับอุปกรณ์นี้อย่างงั้นจริงหรอ การตั้งค่าที่มีอยู่ของอุปกรณ์นี้จะถูกเขียนทับนะ" - saveConfirm: "บันทึกข้อมูลสำรองเป็น {name} มั้ย?" - deleteConfirm: "ลบข้อมูลสำรอง {name} มั้ย?" - renameConfirm: "ต้องการเปลี่ยนชื่อข้อมูลสำรองจาก “{old}” เป็น “{new}” ใช่ไหม?" - noBackups: "ไม่มีข้อมูลสำรอง สามารถบันทึกการตั้งค่าไคลเอนต์ปัจจุบันไปยังเซิร์ฟเวอร์ด้วย “บันทึกข้อมูลสำรองใหม่”" + nameAlreadyExists: "มีการตั้งค่าสำรองชื่อ “{name}” อยู่แล้ว กรุณาป้อนชื่ออื่น" + applyConfirm: "ต้องการใช้การตั้งค่าสำรอง “{name}” กับอุปกรณ์นี้ใช่ไหม? การตั้งค่าที่มีอยู่บนอุปกรณ์นี้จะถูกเขียนทับ" + saveConfirm: "บันทึกการตั้งค่าสำรองเป็น {name} ใช่ไหม?" + deleteConfirm: "ต้องการลบ {name} ใช่ไหม?" + renameConfirm: "ต้องการเปลี่ยนชื่อจาก “{old}” เป็น “{new}” ใช่ไหม?" + noBackups: "ไม่มีการตั้งค่าสำรอง สามารถบันทึกการตั้งค่าไคลเอนต์ปัจจุบันไปยังเซิร์ฟเวอร์ด้วย “บันทึกการตั้งค่าสำรองใหม่”" createdAt: "สร้างเมื่อ: {date} {time}" updatedAt: "อัปเดตเมื่อ: {date} {time}" cannotLoad: "การโหลดล้มเหลว" - invalidFile: "รูปแบบไฟล์ไม่ถูกต้องนะ" + invalidFile: "รูปแบบไฟล์ไม่ถูกต้อง" _registry: scope: "สโคป" key: "คีย์" @@ -1841,13 +1873,13 @@ _menuDisplay: hide: "ซ่อน" _wordMute: muteWords: "ปิดเสียงคำ" - muteWordsDescription: "คั่นด้วยช่องว่างสำหรับเงื่อนไข AND หรือด้วยการขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR นะ" + muteWordsDescription: "คั่นด้วยเว้นวรรคสำหรับเงื่อนไข AND, หรือขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR" muteWordsDescription2: "ล้อมรอบคีย์เวิร์ดด้วยเครื่องหมายทับเพื่อใช้นิพจน์ทั่วไป" _instanceMute: - instanceMuteDescription: "การดำเนินการนี้จะปิดเสียง\"โน้ต/รีโน้ต\"จากอินสแตนซ์ที่อยู่ในรายการ รวมถึงบันทึกของผู้ใช้ที่ตอบกลับผู้ใช้จากอินสแตนซ์ที่ปิดเสียง" + instanceMuteDescription: "ปิดเสียง “โน้ต/รีโน้ต” ทั้งหมดจากเซิร์ฟเวอร์ที่ระบุไว้ รวมถึงโน้ตของผู้ใช้ที่ตอบกลับผู้ใช้จากเซิร์ฟเวอร์ที่ถูกปิดเสียง" instanceMuteDescription2: "คั่นด้วยการขึ้นบรรทัดใหม่" - title: "ซ่อนโน้ตจากอินสแตนซ์ที่มีอยู่ในรายชื่อ" - heading: "รายชื่ออินสแตนซ์ที่ถูกปิดเสียง" + title: "ซ่อนโน้ตจากเซิร์ฟเวอร์ที่มีระบุไว้" + heading: "เซิร์ฟเวอร์ที่ถูกปิดเสียง" _theme: explore: "สำรวจธีม" install: "ติดตั้งธีม" @@ -1911,7 +1943,6 @@ _theme: buttonBg: "ปุ่มพื้นหลัง" buttonHoverBg: "ปุ่มพื้นหลัง (โฮเวอร์)" inputBorder: "เส้นขอบของช่องป้อนข้อมูล" - listItemHoverBg: "รายการไอเทมพื้นหลัง (โฮเวอร์)" driveFolderBg: "พื้นหลังโฟลเดอร์ไดรฟ์" wallpaperOverlay: "วอลล์เปเปอร์ซ้อนทับ" badge: "ตรา" @@ -1923,8 +1954,6 @@ _sfx: note: "โน้ต" noteMy: "โน้ตของตัวเอง" notification: "การเเจ้งเตือน" - antenna: "เสาอากาศ" - channel: "การแจ้งเตือนช่อง" reaction: "เมื่อเลือกรีแอคชั่น" _soundSettings: driveFile: "ใช้เสียงจากไดรฟ์" @@ -1932,7 +1961,8 @@ _soundSettings: driveFileTypeWarn: "ไม่รองรับไฟล์นี้" driveFileTypeWarnDescription: "กรุณาเลือกไฟล์เสียง" driveFileDurationWarn: "เสียงยาวเกินไป" - driveFileDurationWarnDescription: "การใช้เสียงที่ยาวอาจรบกวนการใช้งาน Misskey, ต้องการดำเนินการต่อหรือไม่?" + driveFileDurationWarnDescription: "การใช้เสียงที่ยาว อาจรบกวนการใช้งาน Misskey, ต้องการดำเนินการต่อใช่ไหม?" + driveFileError: "ไม่สามารถโหลดไฟล์เสียงได้ กรุณาเปลี่ยนแปลงการตั้งค่า" _ago: future: "อนาคต" justNow: "เมื่อกี๊นี้" @@ -1976,49 +2006,49 @@ _2fa: removeKey: "ลบคีย์ความปลอดภัยออก" removeKeyConfirm: "ลบข้อมูลสำรอง {name} มั้ย?" whyTOTPOnlyRenew: "ไม่สามารถลบแอปตัวรับรองความถูกต้องได้ตราบใดที่มีการลงทะเบียนคีย์ความปลอดภัยไว้แล้ว" - renewTOTP: "กำหนดค่าแอพตัวตรวจสอบสิทธิ์ใหม่" + renewTOTP: "ตั้งค่าแอปยืนยันตัวตน" renewTOTPConfirm: "วิธีการแบบนี้จะทําให้รหัสยืนยันจากแอพก่อนหน้าของคุณหยุดทํางานเลยนะ" renewTOTPOk: "ตั้งค่าคอนฟิกใหม่" renewTOTPCancel: "ไม่เป็นไร" - checkBackupCodesBeforeCloseThisWizard: "โปรดตรวจสอบรหัสสำรองด้านล่างก่อนที่จะปิดวิซาร์ดนี้" - backupCodes: "รหัสสำรองข้อมูล" + checkBackupCodesBeforeCloseThisWizard: "โปรดตรวจสอบรหัสแบ๊กอัปด้านล่างก่อนที่จะปิดวิซาร์ดนี้" + backupCodes: "รหัสแบ๊กอัป" backupCodesDescription: "หากแอปยืนยันตัวตนของคุณไม่พร้อมใช้งาน คุณสามารถใช้รหัสสำรองด้านล่างเพื่อเข้าถึงบัญชีของคุณได้ อย่าลืมเก็บรหัสเหล่านี้ไว้ในที่ปลอดภัย แต่ละรหัสสามารถใช้ได้เพียงครั้งเดียวเท่านั้น" - backupCodeUsedWarning: "มีการใช้รหัสสำรองแล้ว โปรดกรุณากำหนดค่าการตรวจสอบสิทธิ์แบบสองปัจจัยโดยเร็วที่สุดถ้าหากคุณยังไม่สามารถใช้งานได้อีก" - backupCodesExhaustedWarning: "รหัสสำรองทั้งหมดถูกใช้แล้ว ถ้าหากคุณยังสูญเสียการเข้าถึงแอปการตรวจสอบสิทธิ์แบบสองปัจจัยคุณจะยังไม่สามารถเข้าถึงบัญชีนี้ได้ กรุณากำหนดค่าการรับรองความถูกต้องด้วยการยืนยันสองชั้น" + backupCodeUsedWarning: "รหัสแบ๊กอัปถูกใช้งานแล้ว หากแอปพลิเคชันการยืนยันตัวตนไม่สามารถใช้งานได้ ให้รีบทำการตั้งค่าแอปฯใหม่โดยเร็วที่สุด" + backupCodesExhaustedWarning: "รหัสแบ๊กอัปทั้งหมดถูกใช้งานแล้ว หากยังไม่สามารถใช้แอปพลิเคชันการยืนยันตัวตนได้ก็จะไม่สามารถเข้าถึงบัญชีนี้ได้อีกต่อไป กรุณาลงทะเบียนแอปพลิเคชันการยืนยันตัวตนใหม่" moreDetailedGuideHere: "คลิกที่นี่เพื่อดูคำแนะนำโดยละเอียด" _permissions: - "read:account": "ดูข้อมูลบัญชีของคุณ" - "write:account": "แก้ไขข้อมูลบัญชีของคุณ" - "read:blocks": "ดูรายชื่อผู้ใช้ที่ถูกบล็อกของคุณ" - "write:blocks": "แก้ไขรายชื่อผู้ใช้ที่ถูกบล็อกของคุณ" - "read:drive": "เข้าถึงไฟล์และโฟลเดอร์ในไดรฟ์ของคุณ" - "write:drive": "แก้ไขหรือลบไฟล์และโฟลเดอร์ในไดรฟ์ของคุณ" + "read:account": "ดูข้อมูลบัญชี" + "write:account": "แก้ไขข้อมูลบัญชี" + "read:blocks": "ดูรายชื่อผู้ใช้ที่ถูกบล็อก" + "write:blocks": "แก้ไขรายชื่อผู้ใช้ที่ถูกบล็อก" + "read:drive": "เข้าถึงไดรฟ์" + "write:drive": "จัดการไดรฟ์" "read:favorites": "ดูรายการโปรด" "write:favorites": "แก้ไขรายการโปรด" "read:following": "ดูข้อมูลว่าใครที่คุณติดตาม" "write:following": "ติดตามหรือเลิกติดตามบัญชีอื่น" - "read:messaging": "ดูแชทของคุณ" + "read:messaging": "ดูแชท" "write:messaging": "เขียนหรือลบข้อความแชท" - "read:mutes": "ดูรายชื่อผู้ใช้ที่ปิดเสียงของคุณ" + "read:mutes": "ดูรายชื่อผู้ใช้ที่ถูกปิดเสียง" "write:mutes": "แก้ไขรายชื่อผู้ใช้ที่ถูกปิดเสียง" "write:notes": "เขียนหรือลบโน้ต" - "read:notifications": "ดูการแจ้งเตือนของคุณ" - "write:notifications": "จัดการแจ้งเตือนของคุณ" - "read:reactions": "ดูรีแอคชั่นของคุณ" - "write:reactions": "แก้ไขรีแอคชั่นของคุณ" + "read:notifications": "ดูการแจ้งเตือน" + "write:notifications": "จัดการแจ้งเตือน" + "read:reactions": "ดูรีแอคชั่น" + "write:reactions": "แก้ไขรีแอคชั่น" "write:votes": "โหวตบนสำรวจความคิดเห็น" "read:pages": "ดูหน้าเพจ" - "write:pages": "แก้ไขหรือลบเพจของคุณ" + "write:pages": "แก้ไขหรือลบเพจ" "read:page-likes": "ดูรายการเพจที่ถูกใจไว้" "write:page-likes": "แก้ไขรายการเพจที่ถูกใจ" - "read:user-groups": "ดูกลุ่มผู้ใช้ของคุณ" - "write:user-groups": "แก้ไขหรือลบกลุ่มผู้ใช้ของคุณ" - "read:channels": "ดูแชนแนลของคุณ" - "write:channels": "แก้ไขแชนแนลของคุณ" + "read:user-groups": "ดูกลุ่มผู้ใช้" + "write:user-groups": "แก้ไขหรือลบกลุ่มผู้ใช้" + "read:channels": "ดูช่อง" + "write:channels": "แก้ไขช่อง" "read:gallery": "ดูแกลเลอรี่" - "write:gallery": "แก้ไขแกลเลอรี่ของคุณ" - "read:gallery-likes": "ดูรายการโพสต์แกลเลอรีที่ถูกใจไว้" - "write:gallery-likes": "แก้ไขรายการโพสต์แกลเลอรีที่ถูกใจไว้" + "write:gallery": "แก้ไขแกลเลอรี" + "read:gallery-likes": "ดูแกลเลอรีที่ถูกใจไว้" + "write:gallery-likes": "จัดการแกลเลอรีที่ถูกใจไว้" "read:flash": "ดู Play" "write:flash": "แก้ไข Play" "read:flash-likes": "ดูรายการ play ที่ถูกใจไว้" @@ -2027,20 +2057,20 @@ _permissions: "write:admin:delete-account": "ลบบัญชีผู้ใช้" "write:admin:delete-all-files-of-a-user": "ลบไฟล์ทั้งหมดของผู้ใช้" "read:admin:index-stats": "ดูข้อมูลเกี่ยวกับดัชนีฐานข้อมูล" - "read:admin:table-stats": "ดูข้อมูลเกี่ยวกับตารางฐานข้อมูล" + "read:admin:table-stats": "ดูข้อมูลเกี่ยวกับตารางในฐานข้อมูล" "read:admin:user-ips": "ดูที่อยู่ IP ของผู้ใช้" - "read:admin:meta": "ดูข้อมูลเมตาของอินสแตนซ์" + "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-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:meta": "จัดการข้อมูลอภิพันธุ์ของอินสแตนซ์" "write:admin:user-note": "จัดการโน้ตการกลั่นกรอง" "write:admin:roles": "จัดการบทบาท" "read:admin:roles": "ดูบทบาท" @@ -2067,14 +2097,14 @@ _permissions: "read:admin:ad": "ดูโฆษณา" "write:invite-codes": "สร้างรหัสเชิญ" "read:invite-codes": "รับรหัสเชิญ" - "write:clip-favorite": "ควบคุมการถูกใจของคลิป" - "read:clip-favorite": "ดูการถูกใจของคลิป" + "write:clip-favorite": "จัดการคลิปที่ถูกใจ" + "read:clip-favorite": "ดูคลิปที่ถูกใจ" "read:federation": "รับข้อมูลเกี่ยวกับสหพันธ์" "write:report-abuse": "รายงานการละเมิด" _auth: shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน" shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?" - shareAccessAsk: "ต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณหรือไม่?" + shareAccessAsk: "ต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณใช่ไหม?" permission: "{name} ได้ขอสิทธิ์การเข้าถึงดังต่อไปนี้" permissionAsk: "แอปพลิเคชันนี้ขอสิทธิ์ดังต่อไปนี้" pleaseGoBack: "กรุณากลับไปที่แอปพลิเคชัน" @@ -2097,7 +2127,7 @@ _weekday: saturday: "วันเสาร์" _widgets: profile: "โปรไฟล์" - instanceInfo: "ข้อมูล อินสแตนซ์" + instanceInfo: "ข้อมูลเซิร์ฟเวอร์" memo: "โน้ตแปะ" notifications: "การเเจ้งเตือน" timeline: "ไทม์ไลน์" @@ -2111,7 +2141,7 @@ _widgets: digitalClock: "นาฬิกาดิจิตอล" unixClock: "นาฬิกา UNIX" federation: "สหพันธ์" - instanceCloud: "อินสแตนซ์คลาวด์" + instanceCloud: "กลุ่มเมฆเซิร์ฟเวอร์" postForm: "แบบฟอร์มการโพสต์" slideshow: "แสดงภาพนิ่ง" button: "ปุ่ม" @@ -2120,7 +2150,7 @@ _widgets: serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์" aiscript: " คอนโซล AiScript" aiscriptApp: "แอป AiScript" - aichan: "ไอ" + aichan: "藍 (ไอ)" userList: "รายชื่อผู้ใช้" _userList: chooseList: "เลือกรายชื่อ" @@ -2144,7 +2174,7 @@ _poll: deadlineTime: "เวลา" duration: "ระยะเวลา" votesCount: "{n} คะแนนเสียง" - totalVotes: "{n} คะแนนเสียงทั้งหมด" + totalVotes: "ทั้งหมด {n} คะแนนเสียง" vote: "โหวต" showResult: "ดูผลลัพธ์" voted: "โหวตแล้ว" @@ -2156,14 +2186,14 @@ _poll: _visibility: public: "สาธารณะ" publicDescription: "โน้ตของคุณจะปรากฏแก่ผู้ใช้ทุกคน" - home: "หน้าแรก" - homeDescription: "โพสลงไทม์ไลน์ที่บ้านเท่านั้น" + home: "หน้าหลัก" + homeDescription: "โพสต์ลงไทม์ไลน์หลักเท่านั้น" followers: "ผู้ติดตาม" followersDescription: "เฉพาะผู้ติดตามเท่านั้นที่มองเห็นได้" specified: "ไดเร็ค" specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น" - disableFederation: "ไม่มีสหพันธ์" - disableFederationDescription: "อย่าส่งไปยังอินสแตนซ์อื่น" + disableFederation: "การปิดใช้งานสหพันธ์" + disableFederationDescription: "อย่าส่งข้อมูลไปยังเซิร์ฟเวอร์อื่น" _postForm: replyPlaceholder: "ตอบกลับโน้ตนี้..." quotePlaceholder: "อ้างโน้ตนี้..." @@ -2199,37 +2229,37 @@ _exportOrImport: userLists: "รายชื่อ" excludeMutingUsers: "ยกเว้นผู้ใช้ที่ปิดเสียง" excludeInactiveUsers: "ยกเว้นผู้ใช้ที่ไม่ได้ใช้งาน" - withReplies: "รวมการตอบกลับจากผู้ใช้ที่นำเข้าไว้ในไทม์ไลน์" + withReplies: "รวมการตอบกลับจากผู้ใช้ที่ถูกนำเข้า ลงไทม์ไลน์" _charts: federation: "สหพันธ์" apRequest: "คำขอ" - usersIncDec: "ความแตกต่างของจำนวนผู้ใช้งาน" + usersIncDec: "การเพิ่มลดของจำนวนผู้ใช้" usersTotal: "จำนวนผู้ใช้งานทั้งหมด" activeUsers: "จำนวนผู้ใช้งานที่ยังมีความเคลื่อนไหวอยู่" - notesIncDec: "ความแตกต่างของจำนวนโน้ต" - localNotesIncDec: "ความแตกต่างของจำนวนโน้ตท้องถิ่น" - remoteNotesIncDec: "ความแตกต่างของจำนวนโน้ตระยะไกล" + notesIncDec: "การเพิ่มลดของจำนวนโน้ต" + localNotesIncDec: "การเพิ่มลดของจำนวนโน้ตท้องถิ่น" + remoteNotesIncDec: "การเพิ่มลดของจำนวนโน้ตระยะไกล" notesTotal: "จำนวนโน้ตทั้งหมด" - filesIncDec: "ความแตกต่างของจำนวนไฟล์" + filesIncDec: "การเพิ่มลดของจำนวนไฟล์" filesTotal: "จำนวนไฟล์ทั้งหมด" - storageUsageIncDec: "ความแตกต่างในการใช้พื้นที่เก็บข้อมูล" + storageUsageIncDec: "การเพิ่มลดในการใช้พื้นที่เก็บข้อมูล" storageUsageTotal: "การใช้พื้นที่เก็บข้อมูลทั้งหมด" _instanceCharts: requests: "คำขอ" - users: "ความแตกต่างของจำนวนผู้ใช้งาน" + users: "การเพิ่มลดของจำนวนผู้ใช้งาน" usersTotal: "จำนวนผู้ใช้งานสะสม" - notes: "ความแตกต่างของจำนวนโน้ต" + notes: "การเพิ่มลดของจำนวนโน้ต" notesTotal: "จำนวนโน้ตสะสม" - ff: "ความแตกต่างของจำนวนผู้ใช้ที่ติดตาม / ผู้ติดตาม" - ffTotal: "จำนวนผู้ใช้งานที่ติดตามสะสม / ผู้ติดตาม" - cacheSize: "ความแตกต่างในขนาดของแคช" - cacheSizeTotal: "ขนาดแคชรวมที่สะสม" - files: "ความแตกต่างของจำนวนไฟล์" + ff: "การเพิ่มลดของการติดตาม/ผู้ติดตาม" + ffTotal: "จำนวนสะสมของการติดตาม/ผู้ติดตาม" + cacheSize: "การเพิ่มลดขนาดของแคช" + cacheSizeTotal: "ขนาดแคชสะสม" + files: "การเพิ่มลดของจำนวนไฟล์" filesTotal: "จำนวนไฟล์สะสม" _timelines: - home: "หน้าแรก" - local: "ในพื้นที่" - social: "โซเชี่ยล" + home: "หน้าหลัก" + local: "ท้องถิ่น" + social: "โซเชียล" global: "ทั่วโลก" _play: new: "สร้าง Play" @@ -2245,7 +2275,7 @@ _play: featured: "เป็นที่นิยม" title: "หัวข้อ" script: "สคริปต์" - summary: "รายละเอียด" + summary: "คำอธิบาย" visibilityDescription: "หากตั้งค่าเป็นส่วนตัว มันจะไม่ปรากฏในโปรไฟล์อีกต่อไป แต่ผู้ที่ทราบ URL ของมันจะยังสามารถเข้าถึงได้" _pages: newPage: "สร้างหน้าเพจใหม่" @@ -2333,13 +2363,14 @@ _notification: mention: "กล่าวถึง" reply: "ตอบกลับ" renote: "รีโน้ต" - quote: "อ้างคำพูด" + quote: "อ้างอิง" reaction: "รีแอคชั่น" pollEnded: "โพลสิ้นสุดแล้ว" receiveFollowRequest: "ได้รับคำร้องขอติดตาม" followRequestAccepted: "อนุมัติให้ติดตามแล้ว" roleAssigned: "ให้บทบาท" achievementEarned: "ปลดล็อกความสำเร็จแล้ว" + login: "เข้าสู่ระบบ" app: "การแจ้งเตือนจากแอปที่มีลิงก์" _actions: followBack: "ติดตามกลับด้วย" @@ -2349,6 +2380,7 @@ _deck: alwaysShowMainColumn: "แสดงคอลัมน์หลักเสมอ" columnAlign: "จัดแนวคอลัมน์" addColumn: "เพิ่มคอลัมน์" + newNoteNotificationSettings: "ตั้งค่าการแจ้งเตือนเมื่อมีโน้ตใหม่" configureColumn: "ตั้งค่าคอลัมน์" swapLeft: "ขยับไปทางซ้าย" swapRight: "ขยับไปทางขวา" @@ -2373,7 +2405,7 @@ _deck: antenna: "เสาอากาศ" list: "รายการ" channel: "ช่อง" - mentions: "พูดถึง" + mentions: "กล่าวถึงคุณ" direct: "ไดเร็กต์" roleTimeline: "บทบาทไทม์ไลน์" _dialog: @@ -2387,9 +2419,10 @@ _drivecleaner: orderByCreatedAtAsc: "วันที่จากน้อยไปหามาก" _webhookSettings: createWebhook: "สร้าง Webhook" + modifyWebhook: "แก้ไข Webhook" name: "ชื่อ" secret: "ความลับ" - events: "อีเว้นท์ Webhook" + trigger: "ทริกเกอร์" active: "เปิดใช้งาน" _events: follow: "เมื่อกำลังติดตามผู้ใช้" @@ -2399,6 +2432,26 @@ _webhookSettings: renote: "รีโน้ตแล้วเมื่อ" reaction: "เมื่อได้รับรีแอคชั่น" mention: "เมื่อกำลังถูกกล่าวถึง" + _systemEvents: + abuseReport: "เมื่อมีการรายงานจากผู้ใช้" + abuseReportResolved: "เมื่อมีการจัดการกับการรายงานจากผู้ใช้" + userCreated: "เมื่อผู้ใช้ถูกสร้างขึ้น" + deleteConfirm: "ต้องการลบ Webhook ใช่ไหม?" +_abuseReport: + _notificationRecipient: + createRecipient: "เพิ่มปลายทางการแจ้งเตือนการรายงาน" + modifyRecipient: "แก้ไขปลายทางการแจ้งเตือนการรายงาน" + recipientType: "ประเภทของปลายทางการแจ้งเตือน\n" + _recipientType: + mail: "อีเมล" + webhook: "Webhook" + _captions: + mail: "ส่งการแจ้งเตือนไปยังที่อยู่อีเมลของผู้ควบคุม (เฉพาะเมื่อได้รับการรายงาน)" + webhook: "ส่งการแจ้งเตือนไปยัง SystemWebhook ที่กำหนด (จะส่งเมื่อได้รับการรายงานและเมื่อการรายงานได้รับการแก้ไข)" + keywords: "คีย์เวิร์ด" + notifiedUser: "ผู้ใช้ที่ได้รับการแจ้งเตือน" + notifiedWebhook: "Webhook ที่ใช้" + deleteConfirm: "ต้องการลบปลายทางการแจ้งเตือนใช่ไหม?" _moderationLogTypes: createRole: "สร้างบทบาทแล้ว" deleteRole: "ลบบทบาทแล้ว" @@ -2421,9 +2474,9 @@ _moderationLogTypes: deleteGlobalAnnouncement: "ลบประกาศทั่วโลกออกแล้ว" deleteUserAnnouncement: "ลบประกาศผู้ใช้ออกแล้ว" resetPassword: "รีเซ็ตรหัสผ่าน" - suspendRemoteInstance: "ระงับอินสแตนซ์ระยะไกล" - unsuspendRemoteInstance: "เลิกระงับอินสแตนซ์ระยะไกล" - updateRemoteInstanceNote: "อัปเดตโน้ตการกลั่นกรองของอินสแตนซ์ระยะไกลแล้ว" + suspendRemoteInstance: "ระงับเซิร์ฟเวอร์ระยะไกล" + unsuspendRemoteInstance: "เลิกระงับเซิร์ฟเวอร์ระยะไกล" + updateRemoteInstanceNote: "อัปเดตโน้ตการกลั่นกรองสำหรับเซิร์ฟเวอร์ระยะไกลแล้ว" markSensitiveDriveFile: "ทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน" unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน" resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว" @@ -2436,6 +2489,12 @@ _moderationLogTypes: deleteAvatarDecoration: "ลบการตกแต่งไอคอนแล้ว" unsetUserAvatar: "ลบไอคอนผู้ใช้" unsetUserBanner: "ลบแบนเนอร์ผู้ใช้" + createSystemWebhook: "สร้าง SystemWebhook" + updateSystemWebhook: "อัปเดต SystemWebhook" + deleteSystemWebhook: "ลบ SystemWebhook" + createAbuseReportNotificationRecipient: "สร้างปลายทางการแจ้งเตือนการรายงาน" + updateAbuseReportNotificationRecipient: "อัปเดตปลายทางการแจ้งเตือนการรายงาน" + deleteAbuseReportNotificationRecipient: "ลบปลายทางการแจ้งเตือนการรายงาน" _fileViewer: title: "รายละเอียดไฟล์" type: "ประเภทไฟล์" @@ -2448,10 +2507,10 @@ _externalResourceInstaller: title: "ติดตั้งจากไซต์ภายนอก" checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง" _plugin: - title: "ต้องการติดตั้งปลั๊กอินนี้หรือไม่?" + title: "ต้องการติดตั้งปลั๊กอินนี้ใช่ไหม?" metaTitle: "ข้อมูลส่วนเสริม" _theme: - title: "ต้องการติดตั้งธีมนี้หรือไม่?" + title: "ต้องการติดตั้งธีมนี้ใช่ไหม?" metaTitle: "ข้อมูลธีม" _meta: base: "โทนสีพื้นฐาน" @@ -2487,7 +2546,7 @@ _externalResourceInstaller: description: "เกิดปัญหาระหว่างการติดตั้งธีม กรุณาลองอีกครั้ง. รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript" _dataSaver: _media: - title: "โหลดมีเดีย" + title: "โหลดสื่อ" description: "กันไม่ให้ภาพและวิดีโอโหลดโดยอัตโนมัติ แตะรูปภาพ/วิดีโอที่ซ่อนอยู่เพื่อโหลด" _avatar: title: "รูปไอคอน" @@ -2567,3 +2626,8 @@ _mediaControls: pip: "รูปภาพในรูปภาม" playbackRate: "ความเร็วในการเล่น" loop: "เล่นวนซ้ำ" +_contextMenu: + title: "เมนูเนื้อหา" + app: "แอปพลิเคชัน" + appWithShift: "แอปฟลิเคชันด้วยปุ่มยกแคร่ (Shift)" + native: "UI ของเบราว์เซอร์" diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index cf6729a81d..fe2f158ff6 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -446,6 +446,7 @@ _notification: reaction: "Tepkiler" receiveFollowRequest: "Takip isteği alındı" followRequestAccepted: "Takip isteği kabul edildi" + login: "Giriş Yap " _actions: reply: "yanıt" renote: "vazgeçme" diff --git a/locales/ug-CN.yml b/locales/ug-CN.yml index e48f64511c..fef26040a5 100644 --- a/locales/ug-CN.yml +++ b/locales/ug-CN.yml @@ -17,3 +17,6 @@ _2fa: renewTOTPCancel: "ئۇنى توختىتىڭ" _widgets: profile: "profile" +_notification: + _types: + login: "كىرىش" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 661ecf19d7..f2262cd71f 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -452,7 +452,6 @@ language: "Мова" uiLanguage: "Мова інтерфейсу" aboutX: "Про {x}" native: "місцевий" -disableDrawer: "Не використовувати висувні меню" noHistory: "Історія порожня" signinHistory: "Історія входів" enableAdvancedMfm: "Увімкнути розширений MFM" @@ -631,10 +630,7 @@ abuseReported: "Дякуємо, вашу скаргу було відправл reporter: "Репортер" reporteeOrigin: "Про кого повідомлено" reporterOrigin: "Хто повідомив" -forwardReport: "Переслати звіт на віддалений інстанс" -forwardReportIsAnonymous: "Замість вашого облікового запису анонімний системний обліковий запис буде відображатися як доповідач на віддаленому інстансі" send: "Відправити" -abuseMarkAsResolved: "Позначити скаргу як вирішену" openInNewTab: "Відкрити в новій вкладці" openInSideView: "Відкрити збоку" defaultNavigationBehaviour: "Поведінка навігації за замовчуванням" @@ -1306,7 +1302,6 @@ _theme: buttonBg: "Фон кнопки" buttonHoverBg: "Фон кнопки (при наведенні)" inputBorder: "Край поля вводу" - listItemHoverBg: "Фон елементу в списку (при наведенні)" driveFolderBg: "Фон папки на диску" wallpaperOverlay: "Накладання шпалер" badge: "Значок" @@ -1318,8 +1313,6 @@ _sfx: note: "Нотатки" noteMy: "Мої нотатки" notification: "Сповіщення" - antenna: "Прийом антени" - channel: "Повідомлення каналу" _ago: future: "Майбутнє" justNow: "Щойно" @@ -1590,6 +1583,7 @@ _notification: reaction: "Реакції" receiveFollowRequest: "Запити на підписку" followRequestAccepted: "Прийняті підписки" + login: "Увійти" app: "Сповіщення від додатків" _actions: reply: "Відповісти" @@ -1622,6 +1616,10 @@ _deck: _webhookSettings: name: "Ім'я" active: "Увімкнено" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "E-mail" _moderationLogTypes: suspend: "Призупинити" resetPassword: "Скинути пароль" diff --git a/locales/uz-UZ.yml b/locales/uz-UZ.yml index 4a930626f4..37a550008a 100644 --- a/locales/uz-UZ.yml +++ b/locales/uz-UZ.yml @@ -471,7 +471,6 @@ uiLanguage: "Interfeys tili" aboutX: "{x} haqida" emojiStyle: "Emoji ko'rinishi" native: "Mahalliy" -disableDrawer: "Slayd menyusidan foydalanmang" showNoteActionsOnlyHover: "Eslatma amallarini faqat sichqonchani olib borganda ko‘rsatish" noHistory: "Tarix yo'q" signinHistory: "kirish tarixi" @@ -630,10 +629,7 @@ abuseReported: "Shikoyatingiz yetkazildi. Ma'lumot uchun rahmat." reporter: "Shikoyat qiluvchi" reporteeOrigin: "Xabarning kelib chiqishi" reporterOrigin: "Xabarchining joylashuvi" -forwardReport: "Xabarni masofadagi serverga yuborish" -forwardReportIsAnonymous: "Sizning yuborayotgan xabaringiz o'z akkountingiz emas balki anonim tarzda qoladi" send: "Yuborish" -abuseMarkAsResolved: "Yuborilgan xabarni hal qilingan deb belgilash" openInNewTab: "Yangi tab da ochish" openInSideView: "Yon panelda ochish" defaultNavigationBehaviour: "Standart navigatsiya harakati" @@ -1058,6 +1054,7 @@ _notification: quote: "Iqtibos keltirish" reaction: "Reaktsiyalar" receiveFollowRequest: "Qabul qilingan kuzatuv so'rovlari" + login: "Kirish" _actions: reply: "Javob berish" renote: "Qayta qayd qilish" @@ -1089,6 +1086,10 @@ _webhookSettings: _events: renote: "Qayta qayd qilinganda" mention: "Eslanganda" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: suspend: "To'xtatish" resetPassword: "Parolni tiklash" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index acc2e0c6a9..235497d844 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -376,6 +376,7 @@ mcaptcha: "mCaptcha" enableMcaptcha: "Bật mCaptcha" mcaptchaSiteKey: "Khóa của trang" mcaptchaSecretKey: "Khóa bí mật" +mcaptchaInstanceUrl: "URL mCaptcha máy chủ" recaptcha: "reCAPTCHA" enableRecaptcha: "Bật reCAPTCHA" recaptchaSiteKey: "Khóa của trang" @@ -426,6 +427,7 @@ moderator: "Kiểm duyệt viên" moderation: "Kiểm duyệt" moderationNote: "Ghi chú kiểm duyệt" addModerationNote: "Thêm ghi chú kiểm duyệt" +moderationLogs: "Nhật kí quản trị" nUsersMentioned: "Dùng bởi {n} người" securityKeyAndPasskey: "Mã bảo mật・Passkey" securityKey: "Khóa bảo mật" @@ -458,6 +460,7 @@ retype: "Nhập lại" noteOf: "Tút của {user}" quoteAttached: "Trích dẫn" quoteQuestion: "Trích dẫn lại?" +attachAsFileQuestion: "Văn bản ở trong bộ nhớ tạm rất dài. Bạn có muốn đăng nó dưới dạng một tệp văn bản không?" noMessagesYet: "Chưa có tin nhắn" newMessageExists: "Bạn có tin nhắn mới" onlyOneFileCanBeAttached: "Bạn chỉ có thể đính kèm một tập tin" @@ -483,7 +486,6 @@ uiLanguage: "Ngôn ngữ giao diện" aboutX: "Giới thiệu {x}" emojiStyle: "Kiểu cách Emoji" native: "Bản xứ" -disableDrawer: "Không dùng menu thanh bên" showNoteActionsOnlyHover: "Chỉ hiển thị các hành động ghi chú khi di chuột" noHistory: "Không có dữ liệu" signinHistory: "Lịch sử đăng nhập" @@ -673,10 +675,7 @@ abuseReported: "Báo cáo đã được gửi. Cảm ơn bạn nhiều." reporter: "Người báo cáo" reporteeOrigin: "Bị báo cáo" reporterOrigin: "Máy chủ người báo cáo" -forwardReport: "Chuyển tiếp báo cáo cho máy chủ từ xa" -forwardReportIsAnonymous: "Thay vì tài khoản của bạn, một tài khoản hệ thống ẩn danh sẽ được hiển thị dưới dạng người báo cáo ở máy chủ từ xa." send: "Gửi" -abuseMarkAsResolved: "Đánh dấu đã xử lý" openInNewTab: "Mở trong tab mới" openInSideView: "Mở trong thanh bên" defaultNavigationBehaviour: "Thao tác điều hướng mặc định" @@ -1547,7 +1546,6 @@ _theme: buttonBg: "Nền nút" buttonHoverBg: "Nền nút (Chạm)" inputBorder: "Đường viền khung soạn thảo" - listItemHoverBg: "Nền mục liệt kê (Chạm)" driveFolderBg: "Nền thư mục Ổ đĩa" wallpaperOverlay: "Lớp phủ hình nền" badge: "Huy hiệu" @@ -1559,8 +1557,6 @@ _sfx: note: "Tút" noteMy: "Tút của tôi" notification: "Thông báo" - antenna: "Trạm phát sóng" - channel: "Kênh" _ago: future: "Tương lai" justNow: "Vừa xong" @@ -1878,6 +1874,7 @@ _notification: receiveFollowRequest: "Yêu cầu theo dõi" followRequestAccepted: "Yêu cầu theo dõi được chấp nhận" achievementEarned: "Hoàn thành Achievement" + login: "Đăng nhập" app: "Từ app liên kết" _actions: followBack: "đã theo dõi lại bạn" @@ -1917,11 +1914,14 @@ _webhookSettings: createWebhook: "Tạo Webhook" name: "Tên" secret: "Mã bí mật" - events: "Sự kiện Webhook" active: "Đã bật" _events: reaction: "Khi nhận được sự kiện" mention: "Khi có người nhắc tới bạn" +_abuseReport: + _notificationRecipient: + _recipientType: + mail: "Email" _moderationLogTypes: suspend: "Vô hiệu hóa" resetPassword: "Đặt lại mật khẩu" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index f92d997b5a..8b681efb13 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -8,6 +8,9 @@ search: "搜索" notifications: "通知" username: "用户名" password: "密码" +initialPasswordForSetup: "初始化密码" +initialPasswordIsIncorrect: "初始化密码不正确" +initialPasswordForSetupDescription: "如果是自己安装的 Misskey,请输入配置文件里设好的密码。\n如果使用的是 Misskey 的托管服务等,请输入服务商提供的密码。\n如果没有设置密码,请留空并继续。" forgotPassword: "忘记密码" fetchingAsApObject: "在联邦宇宙查询中..." ok: "OK" @@ -60,6 +63,7 @@ copyFileId: "复制文件ID" copyFolderId: "复制文件夹ID" copyProfileUrl: "复制个人资料URL" searchUser: "搜索用户" +searchThisUsersNotes: "搜索用户帖子" reply: "回复" loadMore: "查看更多" showMore: "查看更多" @@ -89,7 +93,7 @@ followsYou: "正在关注你" createList: "创建列表" manageLists: "管理列表" error: "错误" -somethingHappened: "出现了一些问题!" +somethingHappened: "出错了" retry: "重试" pageLoadError: "页面加载失败。" pageLoadErrorDescription: "这通常是由于网络或浏览器缓存的原因。请清除缓存或等待片刻后重试。" @@ -154,6 +158,7 @@ editList: "编辑列表" selectChannel: "选择频道" selectAntenna: "选择天线" editAntenna: "编辑天线" +createAntenna: "创建天线" selectWidget: "选择小工具" editWidgets: "编辑部件" editWidgetsExit: "完成编辑" @@ -165,7 +170,7 @@ emojiUrl: "emoji 地址" addEmoji: "添加表情符号" settingGuide: "推荐配置" cacheRemoteFiles: "缓存远程文件" -cacheRemoteFilesDescription: "启用此设定时,将在此服务器上缓存远程文件。虽然可以加快图片显示的速度,但是相对的会消耗大量的服务器存储空间。用户角色内的网盘容量决定了这个远程用户能在服务器上保留保留多少缓存。当超出了这个限制时,旧的文件将从缓存中被删除,成为链接。当禁用此设定时,则是从一开始就将远程文件保留为链接。此时推荐将 default.yml 的 proxyRemoteFiles 设置为 true 以优化缩略图生成及保护用户隐私。" +cacheRemoteFilesDescription: "启用此设定时,将在此服务器上缓存远程文件。虽然可以加快图片显示的速度,但是相对的会消耗大量的服务器存储空间。用户角色内的网盘容量决定了这个远程用户能在服务器上保留多少缓存。当超出了这个限制时,旧的文件将从缓存中被删除,成为链接。当禁用此设定时,则是从一开始就将远程文件保留为链接。此时推荐将 default.yml 的 proxyRemoteFiles 设置为 true 以优化缩略图生成及保护用户隐私。" youCanCleanRemoteFilesCache: "可以使用文件管理的🗑️按钮来删除所有的缓存。" cacheRemoteSensitiveFiles: "缓存远程敏感媒体文件" cacheRemoteSensitiveFilesDescription: "如果禁用这项设定,远程服务器的敏感媒体将不会被缓存,而是直接链接。" @@ -180,6 +185,10 @@ addAccount: "添加账户" reloadAccountsList: "更新账户列表" loginFailed: "登录失败" showOnRemote: "转到所在服务器显示" +continueOnRemote: "转到所在服务器继续" +chooseServerOnMisskeyHub: "从 Misskey Hub 选择服务器" +specifyServerHost: "直接输入服务器域名" +inputHostName: "请输入域名" general: "常规设置" wallpaper: "壁纸" setWallpaper: "设置壁纸" @@ -190,6 +199,7 @@ followConfirm: "你确定要关注 {name} 吗?" proxyAccount: "代理账户" proxyAccountDescription: "代理账户是在某些情况下替代用户进行远程关注用的账户。 例如说,当用户将一位远程用户放入一个列表中时,如果本地服务器上没有任何人关注这位远程用户,则这位远程用户的账户活动将不会被送到本地服务器上。作为替代,此时将使用代理账户进行关注。" host: "主机名" +selectSelf: "选择自己" selectUser: "选择用户" recipient: "收件人" annotation: "注解" @@ -205,6 +215,7 @@ perDay: "每天" stopActivityDelivery: "停止发送活动" blockThisInstance: "阻止此服务器向本服务器推流" silenceThisInstance: "使服务器静音" +mediaSilenceThisInstance: "隐藏此服务器的媒体文件" operations: "操作" software: "软件" version: "版本" @@ -223,9 +234,13 @@ clearQueueConfirmText: "未送达的帖子将不会被投递。 通常无需执 clearCachedFiles: "清除缓存" clearCachedFilesConfirm: "确定要清除所有缓存的远程文件?" blockedInstances: "被封锁的服务器" -blockedInstancesDescription: "设定要封锁的服务器,以换行来进行分割。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。" +blockedInstancesDescription: "设定要封锁的服务器,以换行分隔。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。" silencedInstances: "被静音的服务器" -silencedInstancesDescription: "设置要静音的服务器,以换行符分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。" +silencedInstancesDescription: "设置要静音的服务器,以换行分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。" +mediaSilencedInstances: "已隐藏媒体文件的服务器" +mediaSilencedInstancesDescription: "设置要隐藏媒体文件的服务器,以换行分隔。被设置为隐藏媒体文件服务器内所有账号的文件均按照「敏感内容」处理,且将无法使用自定义表情符号。被阻止的实例不受影响。" +federationAllowedHosts: "允许联合的服务器" +federationAllowedHostsDescription: "设定允许联合的服务器,以换行分隔。" muteAndBlock: "静音/拉黑" mutedUsers: "已静音用户" blockedUsers: "已拉黑的用户" @@ -324,6 +339,7 @@ renameFolder: "重命名文件夹" deleteFolder: "删除文件夹" folder: "文件夹" addFile: "添加文件" +showFile: "显示文件" emptyDrive: "网盘中无文件" emptyFolder: "此文件夹中无文件" unableToDelete: "无法删除" @@ -351,7 +367,7 @@ instanceName: "服务器名称" instanceDescription: "服务器简介" maintainerName: "管理员名称" maintainerEmail: "管理员电子邮箱" -tosUrl: "服务条款 URL" +tosUrl: "服务条款地址" thisYear: "今年" thisMonth: "本月" today: "今天" @@ -433,11 +449,12 @@ administrator: "管理员" token: "Token (令牌)" 2fa: "双因素认证" setupOf2fa: "设置双因素认证" -totp: "身份验证应用" -totpDescription: "使用认证应用输入一次性密码。" +totp: "验证器" +totpDescription: "使用验证器输入一次性密码" moderator: "监察员" moderation: "管理" moderationNote: "管理笔记" +moderationNoteDescription: "可以用来记录仅在管理员之间共享的笔记。" addModerationNote: "添加管理笔记" moderationLogs: "管理日志" nUsersMentioned: "{n} 被提到" @@ -477,6 +494,7 @@ noMessagesYet: "现在没有新的聊天" newMessageExists: "新信息" onlyOneFileCanBeAttached: "只能添加一个附件" signinRequired: "请先登录" +signinOrContinueOnRemote: "若要继续,需要转到您所使用的实例,或者在此服务器上注册或登录。" invitations: "邀请" invitationCode: "邀请码" checking: "正在确认" @@ -498,7 +516,10 @@ uiLanguage: "显示语言" aboutX: "关于 {x}" emojiStyle: "表情符号的样式" native: "原生" -disableDrawer: "不显示抽屉菜单" +menuStyle: "菜单样式" +style: "样式" +drawer: "抽屉" +popup: "弹窗" showNoteActionsOnlyHover: "仅在悬停时显示帖子操作" showReactionsCount: "显示帖子的回应数" noHistory: "没有历史记录" @@ -581,6 +602,8 @@ ascendingOrder: "升序" descendingOrder: "降序" scratchpad: "AiScript 控制台" scratchpadDescription: "AiScript 控制台为 AiScript 提供了实验环境。您可以编写代码与 Misskey 交互,运行并查看结果。" +uiInspector: "UI 检查器" +uiInspectorDescription: "查看所有内存中由 UI 组件生成出的实例。UI 组件由 UI:C 系列函数所生成。" output: "输出" script: "脚本" disablePagesScript: "禁用页面脚本" @@ -697,10 +720,7 @@ abuseReported: "内容已发送。感谢您提交信息。" reporter: "举报者" reporteeOrigin: "举报来源" reporterOrigin: "举报者来源" -forwardReport: "将该举报信息转发给远程服务器" -forwardReportIsAnonymous: "在远程实例上显示的报告者是匿名的系统账号,而不是您的账号。" send: "发送" -abuseMarkAsResolved: "处理完毕" openInNewTab: "在新标签页中打开" openInSideView: "在侧边栏中打开" defaultNavigationBehaviour: "默认导航" @@ -837,6 +857,7 @@ administration: "管理" accounts: "账户" switch: "切换" noMaintainerInformationWarning: "管理人员信息未设置。" +noInquiryUrlWarning: "尚未设置联络地址。" noBotProtectionWarning: "Bot 防御未设置。" configure: "设置" postToGallery: "发送到图库" @@ -848,7 +869,7 @@ shareWithNote: "在帖子中分享" ads: "广告" expiration: "截止时间" startingperiod: "开始时间" -memo: "便笺" +memo: "备注" priority: "优先级" high: "高" middle: "中" @@ -901,6 +922,7 @@ followersVisibility: "关注者的公开范围" continueThread: "查看更多帖子" deleteAccountConfirm: "将要删除账户。是否确认?" incorrectPassword: "密码错误" +incorrectTotp: "一次性密码不正确或已过期" voteConfirm: "确定投给 “{choice}” ?" hide: "隐藏" useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示" @@ -1100,6 +1122,8 @@ preservedUsernames: "保留的用户名" preservedUsernamesDescription: "列出需要保留的用户名,使用换行来作为分割。被指定的用户名在建立账户时无法使用,但由管理员所创建的账户不受该限制。此外,现有的账户也不会受到影响。" createNoteFromTheFile: "从文件创建帖子" archive: "归档" +archived: "已归档" +unarchive: "取消归档" channelArchiveConfirmTitle: "要将 {name} 归档吗?" channelArchiveConfirmDescription: "归档后,在频道列表与搜索结果中不会显示,也无法发布新的贴文。" thisChannelArchived: "该频道已被归档。" @@ -1110,6 +1134,9 @@ preventAiLearning: "拒绝接受生成式 AI 的学习" preventAiLearningDescription: "要求文章生成 AI 或图像生成 AI 不能够以发布的帖子和图像等内容作为学习对象。这是通过在 HTML 响应中包含 noai 标志来实现的,这不能完全阻止 AI 学习你的发布内容,并不是所有 AI 都会遵守这类请求。" options: "选项" specifyUser: "用户指定" +lookupConfirm: "确定查询?" +openTagPageConfirm: "确定打开话题标签页面?" +specifyHost: "指定主机名" failedToPreviewUrl: "无法预览" update: "更新" rolesThatCanBeUsedThisEmojiAsReaction: "可以使用表情作为回应的角色" @@ -1172,15 +1199,15 @@ followingOrFollower: "关注中或关注者" fileAttachedOnly: "仅限媒体" showRepliesToOthersInTimeline: "在时间线中包含给别人的回复" hideRepliesToOthersInTimeline: "在时间线中隐藏给别人的回复" -showRepliesToOthersInTimelineAll: "在时间线中包含现在关注的所有人的回复" -hideRepliesToOthersInTimelineAll: "在时间线中隐藏现在关注的所有人的回复" -confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中包含现在关注的所有人的回复吗?" -confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏现在关注的所有人的回复吗?" +showRepliesToOthersInTimelineAll: "在时间线中显示所有现在关注的人的回复" +hideRepliesToOthersInTimelineAll: "在时间线中隐藏所有现在关注的人的回复" +confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中显示所有现在关注的人的回复吗?" +confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏所有现在关注的人的回复吗?" externalServices: "外部服务" sourceCode: "源代码" sourceCodeIsNotYetProvided: "还未提供源代码。要解决此问题请联系管理员。" repositoryUrl: "仓库地址" -repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若是按原样使用 Misskey(并未追加或者修改代码)的情况请填入 https://github.com/misskey-dev/misskey。" +repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若并未追加或者修改 Misskey 的代码,请填入 https://github.com/misskey-dev/misskey。" repositoryUrlOrTarballRequired: "若仓库并未公开,则需要提供 tarball 作为替代。详情请看 .config/example.yml。" feedback: "反馈" feedbackUrl: "反馈地址" @@ -1241,6 +1268,32 @@ keepOriginalFilenameDescription: "若关闭此设置,上传文件时文件名 noDescription: "没有描述" alwaysConfirmFollow: "总是确认关注" inquiry: "联系我们" +tryAgain: "请再试一次" +confirmWhenRevealingSensitiveMedia: "显示敏感内容前需要确认" +sensitiveMediaRevealConfirm: "这是敏感内容。是否显示?" +createdLists: "已创建的列表" +createdAntennas: "已创建的天线" +fromX: "从 {x}" +genEmbedCode: "生成嵌入代码" +noteOfThisUser: "此用户的帖子" +clipNoteLimitExceeded: "无法再往此便签内添加更多帖子" +performance: "性能" +modified: "有变更" +discard: "取消" +thereAreNChanges: "有 {n} 处更改" +signinWithPasskey: "使用通行密钥登录" +unknownWebAuthnKey: "此通行密钥未注册。" +passkeyVerificationFailed: "验证通行密钥失败。" +passkeyVerificationSucceededButPasswordlessLoginDisabled: "通行密钥验证成功,但账户未开启无密码登录。" +messageToFollower: "给关注者的消息" +target: "对象" +_abuseUserReport: + forward: "转发" + forwardDescription: "目标是匿名系统账户,将把举报转发给远程服务器。" + resolve: "解决" + accept: "确认" + reject: "拒绝" + resolveTutorial: "如果举报内容有理且已解决,选择「确认」将案件以肯定的态度标记为已解决。\n如果举报内容站不住脚,选择「拒绝」将案件以否定的态度标记为已解决。" _delivery: status: "投递状态" stop: "停止投递" @@ -1375,6 +1428,9 @@ _serverSettings: fanoutTimelineDescription: "当启用时,可显著提高获取各种时间线时的性能,并减轻数据库的负荷。但是相对的 Redis 的内存使用量将会增加。如果服务器的内存不是很大,又或者运行不稳定的话可以把它关掉。" fanoutTimelineDbFallback: "回退到数据库" fanoutTimelineDbFallbackDescription: "当启用时,若时间线未被缓存,则将额外查询数据库。禁用该功能可通过不执行回退处理进一步减少服务器负载,但会限制可检索的时间线范围。" + reactionsBufferingDescription: "开启时可显著提高发送回应时的性能,及减轻数据库负荷。但 Redis 的内存用量会相应增加。" + inquiryUrl: "联络地址" + inquiryUrlDescription: "用来指定诸如向服务运营商咨询的论坛地址,或记载了运营商联系方式之类的网页地址。" _accountMigration: moveFrom: "从别的账号迁移到此账户" moveFromSub: "为另一个账户建立别名" @@ -1574,7 +1630,7 @@ _achievements: _postedAt0min0sec: title: "报时" description: "在 0 点发布一篇帖子" - flavor: "嘣 嘣 嘣 Biu——!" + flavor: "嘟 · 嘟 · 嘟 · 哔——" _selfQuote: title: "自我引用" description: "引用了自己的帖子" @@ -1623,8 +1679,8 @@ _achievements: flavor: "今年也请对本服务器多多指教!" _cookieClicked: title: "点击饼干小游戏" - description: "点击了可疑的饼干" - flavor: "是不是软件有问题?" + description: "点击了饼干" + flavor: "用错软件了?" _brainDiver: title: "Brain Diver" description: "发布了包含 Brain Diver 链接的帖子" @@ -1641,6 +1697,7 @@ _achievements: _bubbleGameDoubleExplodingHead: title: "两个🤯" description: "你合成出了2个游戏里最大的Emoji" + flavor: "大约能 装满 这些便当盒 🤯 🤯 (比划)" _role: new: "创建角色" edit: "编辑角色" @@ -1670,8 +1727,8 @@ _role: descriptionOfIsExplorable: "打开后将公开角色时间线。如果角色不是公开的,就无法公开时间线。" displayOrder: "显示顺序" descriptionOfDisplayOrder: "数字越大,显示位置越靠前。" - canEditMembersByModerator: "允许监察者编辑成员" - descriptionOfCanEditMembersByModerator: "如果选中,监察者和管理员都能够为用户分配/取消分配角色。如果未选中,则只有管理员可以执行此操作。" + canEditMembersByModerator: "允许监察员编辑成员" + descriptionOfCanEditMembersByModerator: "如果选中,监察员和管理员都能够为用户分配/取消分配角色。如果未选中,则只有管理员可以执行此操作。" priority: "优先级" _priority: low: "低" @@ -1690,6 +1747,7 @@ _role: canManageAvatarDecorations: "管理头像挂件" driveCapacity: "网盘容量" alwaysMarkNsfw: "总是将文件标记为 NSFW" + canUpdateBioMedia: "可以更新头像和横幅" pinMax: "帖子置顶数量限制" antennaMax: "可创建的最大天线数量" wordMuteMax: "屏蔽词的字数限制" @@ -1704,6 +1762,11 @@ _role: canSearchNotes: "是否可以搜索帖子" canUseTranslator: "使用翻译功能" avatarDecorationLimit: "可添加头像挂件的最大个数" + canImportAntennas: "允许导入天线" + canImportBlocking: "允许导入拉黑列表" + canImportFollowing: "允许导入关注列表" + canImportMuting: "允许导入屏蔽列表" + canImportUserLists: "允许导入用户列表" _condition: roleAssignedTo: "已分配给手动角色" isLocal: "是本地用户" @@ -1921,7 +1984,6 @@ _theme: buttonBg: "按钮背景" buttonHoverBg: "按钮背景(悬停)" inputBorder: "输入框边框" - listItemHoverBg: "下拉列表项目背景(悬停)" driveFolderBg: "网盘的文件夹背景" wallpaperOverlay: "壁纸叠加层" badge: "徽章" @@ -1933,8 +1995,6 @@ _sfx: note: "帖子" noteMy: "我的帖子" notification: "通知" - antenna: "天线接收" - channel: "频道通知" reaction: "选择回应时" _soundSettings: driveFile: "使用网盘内的音频" @@ -1943,6 +2003,7 @@ _soundSettings: driveFileTypeWarnDescription: "请选择音频文件" driveFileDurationWarn: "音频过长" driveFileDurationWarnDescription: "使用长音频可能会影响 Misskey 的使用。即使这样也要继续吗?" + driveFileError: "无法读取声音。请更改设置。" _ago: future: "未来" justNow: "最近" @@ -1969,7 +2030,7 @@ _time: day: "日" _2fa: alreadyRegistered: "此设备已被注册" - registerTOTP: "开始设置认证应用" + registerTOTP: "开始设置验证器" step1: "首先,在您的设备上安装验证应用,例如 {a} 或 {b}。" step2: "然后,扫描屏幕上显示的二维码。" step2Uri: "如果使用桌面应用程序的话,请输入下面的 URI" @@ -1978,23 +2039,23 @@ _2fa: setupCompleted: "设置完成" step4: "从现在开始,任何登录操作都将要求您提供动态口令。" securityKeyNotSupported: "您的浏览器不支持安全密钥。" - registerTOTPBeforeKey: "要注册安全密钥或 Passkey,请先设置验证器应用程序。" + registerTOTPBeforeKey: "要注册安全密钥或 Passkey,请先设置验证器。" securityKeyInfo: "注册兼容 WebAuthn 的密钥,例如支持 FIDO2 的硬件安全密钥、设备上的生物识别功能、PIN 码以及 Passkey 等。" registerSecurityKey: "注册安全密钥或 Passkey" securityKeyName: "输入密钥名称" tapSecurityKey: "请按照浏览器说明操作来注册安全密钥或 Passkey。" removeKey: "删除安全密钥" removeKeyConfirm: "您确定要删除 {name} 吗?" - whyTOTPOnlyRenew: "如果注册了安全密钥,则无法取消验证器应用程序上的设置。" - renewTOTP: "重置验证器应用程序" - renewTOTPConfirm: "当前验证器应用程序的验证码将不再有效" + whyTOTPOnlyRenew: "当注册了安全密钥时,无法取消使用验证器。" + renewTOTP: "重置验证器" + renewTOTPConfirm: "当前验证器的验证码及备用代码已失效" renewTOTPOk: "重新配置" renewTOTPCancel: "不用,谢谢" checkBackupCodesBeforeCloseThisWizard: "在关闭此窗口前,请确认下面的备用代码" backupCodes: "备用代码" - backupCodesDescription: "如果无法使用认证应用,可以使用以下的备用代码来访问账户。请务必将这些代码保存在安全的地方。每个代码仅可使用一次。" - backupCodeUsedWarning: "已使用备用代码。如果无法使用认证应用,请尽快重新设定。" - backupCodesExhaustedWarning: "已使用完所有的备用代码。如果无法使用认证应用,将无法再访问您的账户。请再次设定认证应用。" + backupCodesDescription: "如果无法使用验证器,可以使用以下的备用代码来访问账户。请务必将这些代码保存在安全的地方。每个代码仅可使用一次。" + backupCodeUsedWarning: "已使用备用代码。若验证器无法使用,请尽快重置验证器。" + backupCodesExhaustedWarning: "已使用完所有的备用代码。若验证器无法使用,则无法再访问您的账户。请重置验证器。" moreDetailedGuideHere: "此处为详细指南" _permissions: "read:account": "查看账户信息" @@ -2199,6 +2260,9 @@ _profile: changeBanner: "修改横幅" verifiedLinkDescription: "如果将内容设置为 URL,当链接所指向的网页内包含自己的个人资料链接时,可以显示一个已验证图标。" avatarDecorationMax: "最多可添加 {max} 个挂件" + followedMessage: "被关注时显示的消息" + followedMessageDescription: "可以设置被关注时向对方显示的短消息。" + followedMessageDescriptionForLockedAccount: "需要批准才能关注的情况下,消息是在被请求被批准后显示。" _exportOrImport: allNotes: "所有帖子" favoritedNotes: "收藏的帖子" @@ -2291,6 +2355,7 @@ _pages: eyeCatchingImageSet: "设置封面图片" eyeCatchingImageRemove: "删除封面图片" chooseBlock: "添加块" + enterSectionTitle: "输入会话标题" selectType: "选择类型" contentBlocks: "内容" inputBlocks: "输入" @@ -2336,6 +2401,8 @@ _notification: renotedBySomeUsers: "{n} 人转发了" followedBySomeUsers: "被 {n} 人关注" flushNotification: "重置通知历史" + exportOfXCompleted: "已完成 {x} 个导出" + login: "有新的登录" _types: all: "全部" note: "用户的新帖子" @@ -2350,6 +2417,9 @@ _notification: followRequestAccepted: "关注请求已通过" roleAssigned: "授予的角色" achievementEarned: "取得的成就" + exportCompleted: "已完成导出" + login: "登录" + test: "测试通知" app: "关联应用的通知" _actions: followBack: "回关" @@ -2398,9 +2468,10 @@ _drivecleaner: orderByCreatedAtAsc: "按添加日期降序排列" _webhookSettings: createWebhook: "创建 Webhook" + modifyWebhook: "编辑 webhook" name: "名称" secret: "密钥" - events: "何时运行 Webhook" + trigger: "触发器" active: "已启用" _events: follow: "关注时" @@ -2410,6 +2481,27 @@ _webhookSettings: renote: "被转发时" reaction: "被回应时" mention: "被提及时" + _systemEvents: + abuseReport: "当收到举报时" + abuseReportResolved: "当举报被处理时" + userCreated: "当用户被创建时" + deleteConfirm: "要删除 webhook 吗?" + testRemarks: "点击开关右侧的按钮,可以发送使用假数据的测试 Webhook。" +_abuseReport: + _notificationRecipient: + createRecipient: "新建举报通知" + modifyRecipient: "编辑举报通知" + recipientType: "通知类型" + _recipientType: + mail: "邮箱" + webhook: "Webhook" + _captions: + mail: "当收到新举报时,向持有监察员权限的用户发送通知邮件" + webhook: "当收到新举报及举报被处理时,使用指定的 SystemWebhook 发送通知" + keywords: "关键字" + notifiedUser: "通知的用户" + notifiedWebhook: "使用的 webhook" + deleteConfirm: "要删除通知吗?" _moderationLogTypes: createRole: "创建角色" deleteRole: "删除角色" @@ -2438,6 +2530,8 @@ _moderationLogTypes: markSensitiveDriveFile: "标记网盘文件为敏感媒体" unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体" resolveAbuseReport: "处理举报" + forwardAbuseReport: "转发举报" + updateAbuseReportNote: "更新举报用管理笔记" createInvitation: "生成邀请码" createAd: "创建了广告" deleteAd: "删除了广告" @@ -2447,6 +2541,16 @@ _moderationLogTypes: deleteAvatarDecoration: "删除头像挂件" unsetUserAvatar: "清除用户头像" unsetUserBanner: "清除用户横幅" + createSystemWebhook: "新建了 SystemWebhook" + updateSystemWebhook: "更新了 SystemWebhook" + deleteSystemWebhook: "删除了 SystemWebhook" + createAbuseReportNotificationRecipient: "新建了举报通知" + updateAbuseReportNotificationRecipient: "更新了举报通知" + deleteAbuseReportNotificationRecipient: "删除了举报通知" + deleteAccount: "删除了账户" + deletePage: "删除了页面" + deleteFlash: "删除了 Play" + deleteGalleryPost: "删除了图库稿件" _fileViewer: title: "文件信息" type: "文件类型" @@ -2578,3 +2682,22 @@ _mediaControls: pip: "画中画" playbackRate: "播放速度" loop: "循环播放" +_contextMenu: + title: "上下文菜单" + app: "应用" + appWithShift: "Shift 键应用" + native: "浏览器的用户界面" +_embedCodeGen: + title: "自定义嵌入代码" + header: "显示标题" + autoload: "连续加载(不推荐)" + maxHeight: "最大高度" + maxHeightDescription: "若将最大值设为 0 则不限制最大高度。为防止小工具无限增高,建议设置一下。" + maxHeightWarn: "最大高度限制已禁用(0)。若这不是您想要的效果,请将最大高度设一个值。" + previewIsNotActual: "由于超出了预览画面可显示的范围,因此显示内容会与实际嵌入时有所不同。" + rounded: "圆角" + border: "外边框" + applyToPreview: "应用预览" + generateCode: "生成嵌入代码" + codeGenerated: "已生成代码" + codeGeneratedDescription: "将生成的代码贴到网站上来使用。" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index aac3f7662c..55b504e8fb 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -8,6 +8,9 @@ search: "搜尋" notifications: "通知" username: "使用者名稱" password: "密碼" +initialPasswordForSetup: "初始設定用的密碼" +initialPasswordIsIncorrect: "初始設定用的密碼錯誤。" +initialPasswordForSetupDescription: "如果您自己安裝了 Misskey,請使用您在設定檔中輸入的密碼。\n如果您使用 Misskey 的託管服務之類的服務,請使用提供的密碼。\n如果您尚未設定密碼,請將其留空並繼續。" forgotPassword: "忘記密碼" fetchingAsApObject: "從聯邦宇宙取得中..." ok: "OK" @@ -60,6 +63,7 @@ copyFileId: "複製檔案 ID" copyFolderId: "複製資料夾ID" copyProfileUrl: "複製個人資料網址" searchUser: "搜尋使用者" +searchThisUsersNotes: "搜尋這個使用者的貼文" reply: "回覆" loadMore: "載入更多" showMore: "載入更多" @@ -154,6 +158,7 @@ editList: "編輯清單" selectChannel: "選擇頻道" selectAntenna: "選擇天線" editAntenna: "編輯天線" +createAntenna: "建立天線" selectWidget: "選擇小工具" editWidgets: "編輯小工具" editWidgetsExit: "完成" @@ -180,6 +185,10 @@ addAccount: "新增帳戶" reloadAccountsList: "更新帳戶清單的資訊" loginFailed: "登入失敗" showOnRemote: "轉到所在實例顯示" +continueOnRemote: "在遠端伺服器繼續" +chooseServerOnMisskeyHub: "從 Misskey Hub 選擇伺服器" +specifyServerHost: "直接指定伺服器網域" +inputHostName: "請輸入域名" general: "一般" wallpaper: "桌布" setWallpaper: "設定桌布" @@ -190,6 +199,7 @@ followConfirm: "你真的要追隨{name}嗎?" proxyAccount: "代理帳戶" proxyAccountDescription: "代理帳戶是在特定條件下充當遠端追隨者的帳戶。例如,當使用者新增遠端使用者至其列表時,若沒有本地使用者追隨該遠端使用者,則其活動將不會傳送至伺服器,此時便會由代理帳戶代為追隨以解決問題。" host: "主機" +selectSelf: "選擇自己" selectUser: "選取使用者" recipient: "收件人" annotation: "註解" @@ -205,6 +215,7 @@ perDay: "每日" stopActivityDelivery: "停止發送活動" blockThisInstance: "封鎖此伺服器" silenceThisInstance: "禁言此伺服器" +mediaSilenceThisInstance: "將這個伺服器的媒體設為禁言" operations: "操作" software: "軟體" version: "版本" @@ -226,6 +237,10 @@ blockedInstances: "已封鎖的伺服器" blockedInstancesDescription: "請逐行輸入需要封鎖的伺服器。已封鎖的伺服器將無法與本伺服器進行通訊。" silencedInstances: "被禁言的伺服器" silencedInstancesDescription: "設定要禁言的伺服器主機名稱,以換行分隔。隸屬於禁言伺服器的所有帳戶都將被視為「禁言帳戶」,只能發出「追隨請求」,而且無法提及未追隨的本地帳戶。這不會影響已封鎖的實例。" +mediaSilencedInstances: "媒體被禁言的伺服器" +mediaSilencedInstancesDescription: "設定您想要對媒體設定禁言的伺服器,以換行符號區隔。來自被媒體禁言的伺服器所屬帳戶的所有檔案都會被視為敏感檔案,且自訂表情符號不能使用。被封鎖的伺服器不受影響。" +federationAllowedHosts: "允許聯邦通訊的伺服器" +federationAllowedHostsDescription: "設定允許聯邦通訊的伺服器主機,以換行符號分隔。" muteAndBlock: "靜音和封鎖" mutedUsers: "被靜音的使用者" blockedUsers: "被封鎖的使用者" @@ -243,10 +258,10 @@ noCustomEmojis: "沒有自訂的表情符號" noJobs: "沒有任務" federating: "聯邦運作中" blocked: "已封鎖" -suspended: "已凍結" +suspended: "停止發送" all: "全部" subscribing: "訂閱中" -publishing: "直播中" +publishing: "發送中" notResponding: "沒有回應" instanceFollowing: "追隨的伺服器" instanceFollowers: "伺服器的追隨者" @@ -324,6 +339,7 @@ renameFolder: "重新命名資料夾" deleteFolder: "刪除資料夾" folder: "資料夾" addFile: "加入附件" +showFile: "瀏覽文件" emptyDrive: "雲端硬碟為空" emptyFolder: "資料夾為空" unableToDelete: "無法刪除" @@ -343,7 +359,7 @@ reload: "重新整理" doNothing: "無視" reloadConfirm: "確定要重新整理嗎?" watch: "關注" -unwatch: "取消追隨" +unwatch: "取消關注" accept: "接受" reject: "拒絕" normal: "正常" @@ -477,6 +493,7 @@ noMessagesYet: "沒有訊息" newMessageExists: "有新的訊息" onlyOneFileCanBeAttached: "只能加入一個附件" signinRequired: "請先登入" +signinOrContinueOnRemote: "若要繼續,需前往您所在的伺服器,或者註冊並登入此伺服器" invitations: "邀請" invitationCode: "邀請碼" checking: "確認中" @@ -498,7 +515,10 @@ uiLanguage: "介面語言" aboutX: "關於{x}" emojiStyle: "表情符號的風格" native: "原生" -disableDrawer: "不顯示下拉式選單" +menuStyle: "選單風格" +style: "風格" +drawer: "側邊欄" +popup: "彈出式視窗" showNoteActionsOnlyHover: "僅在游標停留時顯示貼文的操作選項" showReactionsCount: "顯示貼文的反應數目" noHistory: "沒有歷史紀錄" @@ -581,6 +601,8 @@ ascendingOrder: "昇冪" descendingOrder: "降冪" scratchpad: "暫存記憶體" scratchpadDescription: "AiScript 控制臺為 AiScript 的實驗環境。您可以在此編寫、執行和確認程式碼與 Misskey 互動的結果。" +uiInspector: "UI 檢查" +uiInspectorDescription: "您可以看到記憶體中存在的 UI 元件實例的清單。 UI 元件由 Ui:C: 系列函數產生。" output: "輸出" script: "腳本" disablePagesScript: "停用頁面的 AiScript 腳本" @@ -697,10 +719,7 @@ abuseReported: "檢舉完成。感謝您的報告。" reporter: "檢舉者" reporteeOrigin: "檢舉來源" reporterOrigin: "檢舉者來源" -forwardReport: "將報告轉送給遠端伺服器" -forwardReportIsAnonymous: "在遠端實例上看不到您的資訊,顯示的報告者是匿名的系统帳戶。" send: "發送" -abuseMarkAsResolved: "處理完畢" openInNewTab: "在新分頁中開啟" openInSideView: "在側欄中開啟" defaultNavigationBehaviour: "預設導航" @@ -837,6 +856,7 @@ administration: "管理" accounts: "帳戶" switch: "切換" noMaintainerInformationWarning: "尚未設定管理員訊息。" +noInquiryUrlWarning: "尚未設定聯絡表單網址。" noBotProtectionWarning: "尚未設定 Bot 防護。" configure: "設定" postToGallery: "發佈到相簿" @@ -901,6 +921,7 @@ followersVisibility: "追隨者的可見性" continueThread: "查看更多貼文" deleteAccountConfirm: "將要刪除帳戶。是否確定?" incorrectPassword: "密碼錯誤。" +incorrectTotp: "一次性密碼錯誤,或者已過期。" voteConfirm: "確定投給「{choice}」?" hide: "隱藏" useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示" @@ -1100,6 +1121,8 @@ preservedUsernames: "保留的使用者名稱" preservedUsernamesDescription: "換行列舉要保留的使用者名稱。此處出現的名稱將在註冊時禁用,但由管理者建立帳戶則不受此限。此外,既有的帳戶也不受影響。" createNoteFromTheFile: "由此檔案建立貼文" archive: "封存" +archived: "已封存" +unarchive: "取消封存" channelArchiveConfirmTitle: "要封存{name}嗎?" channelArchiveConfirmDescription: "封存後,將不會在頻道列表與搜尋結果中顯示,也無法發佈新貼文。" thisChannelArchived: "這個頻道已被封存。" @@ -1110,6 +1133,9 @@ preventAiLearning: "拒絕接受生成式AI的訓練" preventAiLearningDescription: "要求站外生成式 AI 不使用您發佈的內容訓練模型。此功能會使伺服器於 HTML 回應新增「noai」標籤,而因為要視乎 AI 會否遵守該標籤,所以此功能無法完全阻止所有 AI 使用您的內容。" options: "選項" specifyUser: "指定使用者" +lookupConfirm: "要查詢嗎?" +openTagPageConfirm: "要開啟標籤的頁面嗎?" +specifyHost: "指定主機" failedToPreviewUrl: "無法預覽" update: "更新" rolesThatCanBeUsedThisEmojiAsReaction: "可以使用此表情符號為反應的角色" @@ -1169,7 +1195,7 @@ edited: "已編輯" notificationRecieveConfig: "接受通知的設定" mutualFollow: "互相追隨" followingOrFollower: "追隨中或追隨者" -fileAttachedOnly: "顯示包含附件的貼文" +fileAttachedOnly: "只顯示包含附件的貼文" showRepliesToOthersInTimeline: "顯示給其他人的回覆" hideRepliesToOthersInTimeline: "在時間軸上隱藏給其他人的回覆" showRepliesToOthersInTimelineAll: "在時間軸包含追隨中所有人的回覆" @@ -1241,12 +1267,30 @@ keepOriginalFilenameDescription: "如果關閉此設置,上傳時檔案名稱 noDescription: "沒有說明文字" alwaysConfirmFollow: "點擊追隨時總是顯示確認訊息" inquiry: "聯絡我們" +tryAgain: "請再試一次。" +confirmWhenRevealingSensitiveMedia: "要顯示敏感媒體時需確認" +sensitiveMediaRevealConfirm: "這是敏感媒體。確定要顯示嗎?" +createdLists: "已建立的清單" +createdAntennas: "已建立的天線" +fromX: "自 {x}" +genEmbedCode: "產生嵌入程式碼" +noteOfThisUser: "這個使用者的貼文列表" +clipNoteLimitExceeded: "沒辦法在這個摘錄中增加更多貼文了。" +performance: "性能" +modified: "已變更" +discard: "取消" +thereAreNChanges: "有 {n} 處的變更" +signinWithPasskey: "使用密碼金鑰登入" +unknownWebAuthnKey: "未註冊的金鑰。" +passkeyVerificationFailed: "驗證金鑰失敗。" +passkeyVerificationSucceededButPasswordlessLoginDisabled: "雖然驗證金鑰成功,但是無密碼登入的方式是停用的。" +messageToFollower: "給追隨者的訊息" _delivery: status: "傳送狀態" - stop: "停止傳送" - resume: "恢復傳送" + stop: "停止發送" + resume: "恢復發送" _type: - none: "直播中" + none: "發送中" manuallySuspended: "手動暫停中" goneSuspended: "因為伺服器刪除所以暫停中" autoSuspendedForNotResponding: "因為伺服器沒有回應所以暫停中" @@ -1375,8 +1419,9 @@ _serverSettings: fanoutTimelineDescription: "如果啟用的話,檢索各個時間軸的性能會顯著提昇,資料庫的負荷也會減少。不過,Redis 的記憶體使用量會增加。如果伺服器的記憶體容量比較少或者運行不穩定,可以停用。" fanoutTimelineDbFallback: "資料庫的回退" fanoutTimelineDbFallbackDescription: "若啟用,在時間軸沒有快取的情況下將執行回退處理以額外查詢資料庫。若停用,可以透過不執行回退處理來進一步減少伺服器的負荷,但會限制可取得的時間軸範圍。" + reactionsBufferingDescription: "啟用時,可以顯著提高建立反應時的效能並減少資料庫的負載。 但是,Redis 記憶體使用量會增加。" inquiryUrl: "聯絡表單網址" - inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址或包含運營者聯絡資訊網頁的網址。" + inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址,或包含運營者聯絡資訊網頁的網址。" _accountMigration: moveFrom: "從其他帳戶遷移到這個帳戶" moveFromSub: "為另一個帳戶建立別名" @@ -1693,6 +1738,7 @@ _role: canManageAvatarDecorations: "管理頭像裝飾" driveCapacity: "雲端硬碟容量" alwaysMarkNsfw: "總是將檔案標記為NSFW" + canUpdateBioMedia: "允許更新大頭貼和橫幅" pinMax: "置頂貼文的最大數量" antennaMax: "可建立的天線數量" wordMuteMax: "靜音文字的最大字數" @@ -1707,6 +1753,11 @@ _role: canSearchNotes: "可否搜尋貼文" canUseTranslator: "使用翻譯功能" avatarDecorationLimit: "頭像裝飾的最大設置量" + canImportAntennas: "允許匯入天線" + canImportBlocking: "允許匯入封鎖名單" + canImportFollowing: "允許匯入跟隨名單" + canImportMuting: "允許匯入靜音名單" + canImportUserLists: "允許匯入清單" _condition: roleAssignedTo: "手動指派角色完成" isLocal: "本地使用者" @@ -1924,7 +1975,6 @@ _theme: buttonBg: "按鈕背景" buttonHoverBg: "按鈕背景 (漂浮)" inputBorder: "輸入框邊框" - listItemHoverBg: "列表物品背景 (漂浮)" driveFolderBg: "雲端硬碟文件夾背景" wallpaperOverlay: "壁紙覆蓋層" badge: "徽章" @@ -1936,8 +1986,6 @@ _sfx: note: "貼文" noteMy: "我的貼文" notification: "通知" - antenna: "天線接收" - channel: "頻道通知" reaction: "選擇反應時" _soundSettings: driveFile: "使用雲端硬碟的音效檔案" @@ -1946,6 +1994,7 @@ _soundSettings: driveFileTypeWarnDescription: "請選擇音效檔案" driveFileDurationWarn: "音效太長了" driveFileDurationWarnDescription: "使用長音效檔可能會影響 Misskey 的使用體驗。仍要使用此檔案嗎?" + driveFileError: "無法載入語音。請變更設定" _ago: future: "未來" justNow: "剛剛" @@ -2202,6 +2251,9 @@ _profile: changeBanner: "變更橫幅圖像" verifiedLinkDescription: "如果輸入包含您個人資料的網站 URL,欄位旁邊將出現驗證圖示。" avatarDecorationMax: "最多可以設置 {max} 個裝飾。" + followedMessage: "被追隨時的訊息" + followedMessageDescription: "可以設定被追隨時顯示給對方的訊息。" + followedMessageDescriptionForLockedAccount: "如果追隨是需要審核的話,在允許追隨請求之後顯示。" _exportOrImport: allNotes: "所有貼文" favoritedNotes: "「我的最愛」貼文" @@ -2217,7 +2269,7 @@ _charts: federation: "聯邦宇宙" apRequest: "請求" usersIncDec: "使用者增減" - usersTotal: "使用者總數" + usersTotal: "使用者合計" activeUsers: "活躍使用者" notesIncDec: "貼文増減" localNotesIncDec: "本地貼文増減" @@ -2294,6 +2346,7 @@ _pages: eyeCatchingImageSet: "設定封面影像" eyeCatchingImageRemove: "刪除封面影像" chooseBlock: "新增方塊" + enterSectionTitle: "輸入區段的標題" selectType: "選擇類型" contentBlocks: "內容" inputBlocks: "輸入" @@ -2339,6 +2392,8 @@ _notification: renotedBySomeUsers: "{n}人做了轉發" followedBySomeUsers: "被{n}人追隨了" flushNotification: "重置通知歷史紀錄" + exportOfXCompleted: "{x} 的匯出已完成。" + login: "已登入" _types: all: "全部 " note: "使用者的最新貼文" @@ -2353,6 +2408,9 @@ _notification: followRequestAccepted: "追隨請求已接受" roleAssigned: "已授予角色" achievementEarned: "獲得成就" + exportCompleted: "已完成匯出。" + login: "登入" + test: "通知測試" app: "應用程式通知" _actions: followBack: "追隨回去" @@ -2401,9 +2459,10 @@ _drivecleaner: orderByCreatedAtAsc: "按新增日期降序排列" _webhookSettings: createWebhook: "建立 Webhook" + modifyWebhook: "編輯 Webhook" name: "名字" secret: "密鑰" - events: "何時運行 Webhook" + trigger: "觸發器" active: "已啟用" _events: follow: "當你追隨時" @@ -2413,6 +2472,27 @@ _webhookSettings: renote: "當被轉發時" reaction: "當獲得反應時" mention: "當被提到時" + _systemEvents: + abuseReport: "當使用者檢舉時" + abuseReportResolved: "當處理了使用者的檢舉時" + userCreated: "使用者被新增時" + deleteConfirm: "請問是否要刪除 Webhook?" + testRemarks: "按下切換開關右側的按鈕,就會將假資料發送至 Webhook。" +_abuseReport: + _notificationRecipient: + createRecipient: "新增接收檢舉的通知對象" + modifyRecipient: "編輯接收檢舉的通知對象" + recipientType: "通知對象的種類" + _recipientType: + mail: "電子郵件" + webhook: "Webhook" + _captions: + mail: "寄送到擁有監察員權限的使用者電子郵件地址(僅在收到檢舉時)" + webhook: "向指定的 SystemWebhook 發送通知(在收到檢舉和解決檢舉時發送)" + keywords: "關鍵字" + notifiedUser: "被通知的使用者" + notifiedWebhook: "使用的 Webhook" + deleteConfirm: "確定要刪除通知對象嗎?" _moderationLogTypes: createRole: "新增角色" deleteRole: "刪除角色 " @@ -2450,6 +2530,16 @@ _moderationLogTypes: deleteAvatarDecoration: "刪除頭像裝飾" unsetUserAvatar: "移除使用者的大頭貼" unsetUserBanner: "移除使用者的橫幅圖像" + createSystemWebhook: "建立 SystemWebhook" + updateSystemWebhook: "更新 SystemWebhook" + deleteSystemWebhook: "刪除 SystemWebhook" + createAbuseReportNotificationRecipient: "建立接收檢舉的通知對象" + updateAbuseReportNotificationRecipient: "更新接收檢舉的通知對象" + deleteAbuseReportNotificationRecipient: "刪除接收檢舉的通知對象" + deleteAccount: "刪除帳戶" + deletePage: "刪除頁面" + deleteFlash: "刪除 Play" + deleteGalleryPost: "刪除相簿的貼文" _fileViewer: title: "檔案詳細資訊" type: "檔案類型 " @@ -2581,3 +2671,22 @@ _mediaControls: pip: "畫中畫" playbackRate: "播放速度" loop: "循環播放" +_contextMenu: + title: "內容功能表" + app: "應用程式" + appWithShift: "Shift 鍵應用程式" + native: "瀏覽器的使用者介面" +_embedCodeGen: + title: "自訂嵌入程式碼" + header: "檢視標頭 " + autoload: "自動繼續載入(不建議)" + maxHeight: "最大高度" + maxHeightDescription: "設定為 0 時代表沒有最大值。請指定某個值以避免小工具持續在縱向延伸。" + maxHeightWarn: "最大高度限制已停用(0)。如果這個變更不是您想要的,請將最大高度設定為某個值。" + previewIsNotActual: "由於超出了預覽畫面可顯示的範圍,因此顯示內容會與實際嵌入時有所不同。" + rounded: "圓角" + border: "給外框加上邊框" + applyToPreview: "反映在預覽中" + generateCode: "建立嵌入程式碼" + codeGenerated: "已產生程式碼" + codeGeneratedDescription: "請將產生的程式碼貼到您的網站上。" diff --git a/misskey-assets b/misskey-assets deleted file mode 160000 index 0179793ec8..0000000000 --- a/misskey-assets +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0179793ec891856d6f37a3be16ba4c22f67a81b5 diff --git a/package.json b/package.json index 5adce65415..2c84c55303 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "misskey", - "version": "2024.5.0", + "version": "2024.10.1-beta.3", "codename": "nasubi", "repository": { "type": "git", "url": "https://github.com/misskey-dev/misskey.git" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.6.0", "workspaces": [ + "packages/frontend-shared", "packages/frontend", + "packages/frontend-embed", "packages/backend", "packages/sw", "packages/misskey-js", @@ -21,7 +23,7 @@ "build-assets": "node ./scripts/build-assets.mjs", "build": "pnpm build-pre && pnpm -r build && pnpm build-assets", "build-storybook": "pnpm --filter frontend build-storybook", - "build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api", + "build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api", "start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js", "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js", "init": "pnpm migrate", @@ -35,6 +37,7 @@ "cy:open": "pnpm cypress open --browser --e2e --config-file=cypress.config.ts", "cy:run": "pnpm cypress run", "e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run", + "e2e-dev-container": "cp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run", "jest": "cd packages/backend && pnpm jest", "jest-and-coverage": "cd packages/backend && pnpm jest-and-coverage", "test": "pnpm -r test", @@ -51,24 +54,26 @@ "cssnano": "6.1.2", "execa": "8.0.1", "fast-glob": "3.3.2", - "ignore-walk": "6.0.4", + "ignore-walk": "6.0.5", "js-yaml": "4.1.0", - "postcss": "8.4.38", + "postcss": "8.4.47", "tar": "6.2.1", - "terser": "5.30.3", - "typescript": "5.5.2", - "esbuild": "0.20.2", - "glob": "10.3.12" + "terser": "5.33.0", + "typescript": "5.6.2", + "esbuild": "0.23.1", + "glob": "11.0.0" }, "devDependencies": { - "@types/node": "20.12.7", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", + "@misskey-dev/eslint-plugin": "2.0.3", + "@types/node": "20.14.12", + "@typescript-eslint/eslint-plugin": "7.17.0", + "@typescript-eslint/parser": "7.17.0", "cross-env": "7.0.3", - "cypress": "13.7.3", - "eslint": "8.57.0", + "cypress": "13.14.2", + "eslint": "9.8.0", + "globals": "15.9.0", "ncp": "2.0.0", - "start-server-and-test": "2.0.3" + "start-server-and-test": "2.0.8" }, "optionalDependencies": { "@tensorflow/tfjs-core": "4.4.0" diff --git a/packages/backend/.eslintignore b/packages/backend/.eslintignore deleted file mode 100644 index 790eb90145..0000000000 --- a/packages/backend/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules -/built -/.eslintrc.js -/@types/**/* diff --git a/packages/backend/.eslintrc.cjs b/packages/backend/.eslintrc.cjs deleted file mode 100644 index f9fe4814e6..0000000000 --- a/packages/backend/.eslintrc.cjs +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json', './test/tsconfig.json'], - }, - extends: [ - '../shared/.eslintrc.js', - ], - rules: { - 'import/order': ['warn', { - 'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], - 'pathGroups': [ - { - 'pattern': '@/**', - 'group': 'external', - 'position': 'after' - } - ], - }], - 'no-restricted-globals': [ - 'error', - { - 'name': '__dirname', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - }, - { - 'name': '__filename', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - } - ] - }, -}; diff --git a/packages/backend/assets/api-doc.html b/packages/backend/assets/api-doc.html new file mode 100644 index 0000000000..19e0349d47 --- /dev/null +++ b/packages/backend/assets/api-doc.html @@ -0,0 +1,20 @@ + + + + Misskey API + + + + + + + + + diff --git a/packages/backend/assets/embed.js b/packages/backend/assets/embed.js new file mode 100644 index 0000000000..24fccc1b6c --- /dev/null +++ b/packages/backend/assets/embed.js @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: MIT + */ +//@ts-check +(() => { + /** @type {NodeListOf} */ + const els = document.querySelectorAll('iframe[data-misskey-embed-id]'); + + window.addEventListener('message', function (event) { + els.forEach((el) => { + if (event.source !== el.contentWindow) { + return; + } + + const id = el.dataset.misskeyEmbedId; + + if (event.data.type === 'misskey:embed:ready') { + el.contentWindow?.postMessage({ + type: 'misskey:embedParent:registerIframeId', + payload: { + iframeId: id, + } + }, '*'); + } + if (event.data.type === 'misskey:embed:changeHeight' && event.data.iframeId === id) { + el.style.height = event.data.payload.height + 'px'; + } + }); + }); +})(); diff --git a/packages/backend/assets/redoc.html b/packages/backend/assets/redoc.html deleted file mode 100644 index 2557b4532e..0000000000 --- a/packages/backend/assets/redoc.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Misskey API - - - - - - - - - - - - - diff --git a/packages/backend/assets/tabler-badges/login-2.png b/packages/backend/assets/tabler-badges/login-2.png new file mode 100644 index 0000000000000000000000000000000000000000..f3ca8de3ddd0125ef523a249dd0ebd8d086c7566 GIT binary patch literal 3770 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 {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す backendProcess.kill(); await new Promise(resolve => backendProcess.on('exit', resolve)); backendProcess = undefined; @@ -46,6 +47,7 @@ async function killProc() { ], { stdio: [process.stdin, process.stdout, process.stderr, 'ipc'], + serialization: "json", }) .on('message', async (message) => { if (message.type === 'exit') { diff --git a/packages/backend/scripts/generate_api_json.js b/packages/backend/scripts/generate_api_json.js index b4769ef801..798e243004 100644 --- a/packages/backend/scripts/generate_api_json.js +++ b/packages/backend/scripts/generate_api_json.js @@ -3,11 +3,34 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { loadConfig } from '../built/config.js' -import { genOpenapiSpec } from '../built/server/api/openapi/gen-spec.js' -import { writeFileSync } from "node:fs"; +import { execa } from 'execa'; +import { writeFileSync, existsSync } from "node:fs"; -const config = loadConfig(); -const spec = genOpenapiSpec(config, true); +async function main() { + if (!process.argv.includes('--no-build')) { + await execa('pnpm', ['run', 'build'], { + stdout: process.stdout, + stderr: process.stderr, + }); + } -writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8'); + if (!existsSync('./built')) { + throw new Error('`built` directory does not exist.'); + } + + /** @type {import('../src/config.js')} */ + const { loadConfig } = await import('../built/config.js'); + + /** @type {import('../src/server/api/openapi/gen-spec.js')} */ + const { genOpenapiSpec } = await import('../built/server/api/openapi/gen-spec.js'); + + const config = loadConfig(); + const spec = genOpenapiSpec(config, true); + + writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8'); +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts index 09971e8ca0..6ae8ccfbb3 100644 --- a/packages/backend/src/GlobalModule.ts +++ b/packages/backend/src/GlobalModule.ts @@ -13,6 +13,8 @@ import { createPostgresDataSource } from './postgres.js'; import { RepositoryModule } from './models/RepositoryModule.js'; import { allSettled } from './misc/promise-tracker.js'; import type { Provider, OnApplicationShutdown } from '@nestjs/common'; +import { MiMeta } from '@/models/Meta.js'; +import { GlobalEvents } from './core/GlobalEventService.js'; const $config: Provider = { provide: DI.config, @@ -78,11 +80,76 @@ const $redisForTimelines: Provider = { inject: [DI.config], }; +const $redisForReactions: Provider = { + provide: DI.redisForReactions, + useFactory: (config: Config) => { + return new Redis.Redis(config.redisForReactions); + }, + inject: [DI.config], +}; + +const $meta: Provider = { + provide: DI.meta, + useFactory: async (db: DataSource, redisForSub: Redis.Redis) => { + const meta = await db.transaction(async transactionalEntityManager => { + // 過去のバグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する + const metas = await transactionalEntityManager.find(MiMeta, { + order: { + id: 'DESC', + }, + }); + + const meta = metas[0]; + + if (meta) { + return meta; + } else { + // metaが空のときfetchMetaが同時に呼ばれるとここが同時に呼ばれてしまうことがあるのでフェイルセーフなupsertを使う + const saved = await transactionalEntityManager + .upsert( + MiMeta, + { + id: 'x', + }, + ['id'], + ) + .then((x) => transactionalEntityManager.findOneByOrFail(MiMeta, x.identifiers[0])); + + return saved; + } + }); + + async function onMessage(_: string, data: string): Promise { + const obj = JSON.parse(data); + + if (obj.channel === 'internal') { + const { type, body } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'metaUpdated': { + for (const key in body.after) { + (meta as any)[key] = (body.after as any)[key]; + } + meta.proxyAccount = null; // joinなカラムは通常取ってこないので + break; + } + default: + break; + } + } + } + + redisForSub.on('message', onMessage); + + return meta; + }, + inject: [DI.db, DI.redisForSub], +}; + @Global() @Module({ imports: [RepositoryModule], - providers: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines], - exports: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, RepositoryModule], + providers: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions], + exports: [$config, $db, $meta, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForReactions, RepositoryModule], }) export class GlobalModule implements OnApplicationShutdown { constructor( @@ -91,6 +158,7 @@ export class GlobalModule implements OnApplicationShutdown { @Inject(DI.redisForPub) private redisForPub: Redis.Redis, @Inject(DI.redisForSub) private redisForSub: Redis.Redis, @Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis, + @Inject(DI.redisForReactions) private redisForReactions: Redis.Redis, ) { } public async dispose(): Promise { @@ -103,6 +171,7 @@ export class GlobalModule implements OnApplicationShutdown { this.redisForPub.disconnect(), this.redisForSub.disconnect(), this.redisForTimelines.disconnect(), + this.redisForReactions.disconnect(), ]); } diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 0ac521d409..42f1033b9d 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -23,7 +23,7 @@ type RedisOptionsSource = Partial & { * 設定ファイルの型 */ type Source = { - url: string; + url?: string; port?: number; socket?: string; chmodSocket?: string; @@ -31,9 +31,9 @@ type Source = { db: { host: string; port: number; - db: string; - user: string; - pass: string; + db?: string; + user?: string; + pass?: string; disableCache?: boolean; extra?: { [x: string]: string }; }; @@ -49,6 +49,7 @@ type Source = { redisForPubsub?: RedisOptionsSource; redisForJobQueue?: RedisOptionsSource; redisForTimelines?: RedisOptionsSource; + redisForReactions?: RedisOptionsSource; meilisearch?: { host: string; port: string; @@ -62,6 +63,8 @@ type Source = { publishTarballInsteadOfProvideRepositoryUrl?: boolean; + setupPassword?: string; + proxy?: string; proxySmtp?: string; proxyBypassHosts?: string[]; @@ -133,7 +136,7 @@ export type Config = { proxySmtp: string | undefined; proxyBypassHosts: string[] | undefined; allowedPrivateNetworks: string[] | undefined; - maxFileSize: number | undefined; + maxFileSize: number; clusterLimit: number | undefined; id: string; outgoingAddress: string | undefined; @@ -151,6 +154,7 @@ export type Config = { version: string; publishTarballInsteadOfProvideRepositoryUrl: boolean; + setupPassword: string | undefined; host: string; hostname: string; scheme: string; @@ -160,8 +164,10 @@ export type Config = { authUrl: string; driveUrl: string; userAgent: string; - clientEntry: string; - clientManifestExists: boolean; + frontendEntry: string; + frontendManifestExists: boolean; + frontendEmbedEntry: string; + frontendEmbedManifestExists: boolean; mediaProxy: string; externalMediaProxyEnabled: boolean; videoThumbnailGenerator: string | null; @@ -169,6 +175,7 @@ export type Config = { redisForPubsub: RedisOptions & RedisOptionsSource; redisForJobQueue: RedisOptions & RedisOptionsSource; redisForTimelines: RedisOptions & RedisOptionsSource; + redisForReactions: RedisOptions & RedisOptionsSource; sentryForBackend: { options: Partial; enableNodeProfiling: boolean; } | undefined; sentryForFrontend: { options: Partial } | undefined; perChannelMaxNoteCacheCount: number; @@ -196,19 +203,29 @@ const path = process.env.MISSKEY_CONFIG_YML export function loadConfig(): Config { const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../built/meta.json`, 'utf-8')); - const clientManifestExists = fs.existsSync(_dirname + '/../../../built/_vite_/manifest.json'); - const clientManifest = clientManifestExists ? - JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_vite_/manifest.json`, 'utf-8')) + + const frontendManifestExists = fs.existsSync(_dirname + '/../../../built/_frontend_vite_/manifest.json'); + const frontendEmbedManifestExists = fs.existsSync(_dirname + '/../../../built/_frontend_embed_vite_/manifest.json'); + const frontendManifest = frontendManifestExists ? + JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_frontend_vite_/manifest.json`, 'utf-8')) : { 'src/_boot_.ts': { file: 'src/_boot_.ts' } }; + const frontendEmbedManifest = frontendEmbedManifestExists ? + JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_frontend_embed_vite_/manifest.json`, 'utf-8')) + : { 'src/boot.ts': { file: 'src/boot.ts' } }; + const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source; - const url = tryCreateUrl(config.url); + const url = tryCreateUrl(config.url ?? process.env.MISSKEY_URL ?? ''); const version = meta.version; const host = url.host; const hostname = url.hostname; const scheme = url.protocol.replace(/:$/, ''); const wsScheme = scheme.replace('http', 'ws'); + const dbDb = config.db.db ?? process.env.DATABASE_DB ?? ''; + const dbUser = config.db.user ?? process.env.DATABASE_USER ?? ''; + const dbPass = config.db.pass ?? process.env.DATABASE_PASSWORD ?? ''; + const externalMediaProxy = config.mediaProxy ? config.mediaProxy.endsWith('/') ? config.mediaProxy.substring(0, config.mediaProxy.length - 1) : config.mediaProxy : null; @@ -218,6 +235,7 @@ export function loadConfig(): Config { return { version, publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl, + setupPassword: config.setupPassword, url: url.origin, port: config.port ?? parseInt(process.env.PORT ?? '', 10), socket: config.socket, @@ -231,7 +249,7 @@ export function loadConfig(): Config { apiUrl: `${scheme}://${host}/api`, authUrl: `${scheme}://${host}/auth`, driveUrl: `${scheme}://${host}/files`, - db: config.db, + db: { ...config.db, db: dbDb, user: dbUser, pass: dbPass }, dbReplications: config.dbReplications, dbSlaves: config.dbSlaves, meilisearch: config.meilisearch, @@ -239,6 +257,7 @@ export function loadConfig(): Config { redisForPubsub: config.redisForPubsub ? convertRedisOptions(config.redisForPubsub, host) : redis, redisForJobQueue: config.redisForJobQueue ? convertRedisOptions(config.redisForJobQueue, host) : redis, redisForTimelines: config.redisForTimelines ? convertRedisOptions(config.redisForTimelines, host) : redis, + redisForReactions: config.redisForReactions ? convertRedisOptions(config.redisForReactions, host) : redis, sentryForBackend: config.sentryForBackend, sentryForFrontend: config.sentryForFrontend, id: config.id, @@ -246,7 +265,7 @@ export function loadConfig(): Config { proxySmtp: config.proxySmtp, proxyBypassHosts: config.proxyBypassHosts, allowedPrivateNetworks: config.allowedPrivateNetworks, - maxFileSize: config.maxFileSize, + maxFileSize: config.maxFileSize ?? 262144000, clusterLimit: config.clusterLimit, outgoingAddress: config.outgoingAddress, outgoingAddressFamily: config.outgoingAddressFamily, @@ -259,15 +278,17 @@ export function loadConfig(): Config { deliverJobMaxAttempts: config.deliverJobMaxAttempts, inboxJobMaxAttempts: config.inboxJobMaxAttempts, proxyRemoteFiles: config.proxyRemoteFiles, - signToActivityPubGet: config.signToActivityPubGet, + signToActivityPubGet: config.signToActivityPubGet ?? true, mediaProxy: externalMediaProxy ?? internalMediaProxy, externalMediaProxyEnabled: externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy, videoThumbnailGenerator: config.videoThumbnailGenerator ? config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator : null, userAgent: `Misskey/${version} (${config.url})`, - clientEntry: clientManifest['src/_boot_.ts'], - clientManifestExists: clientManifestExists, + frontendEntry: frontendManifest['src/_boot_.ts'], + frontendManifestExists: frontendManifestExists, + frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'], + frontendEmbedManifestExists: frontendEmbedManifestExists, perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000, perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500, deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7), diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index a238f4973a..e3a61861f4 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -8,6 +8,8 @@ export const MAX_NOTE_TEXT_LENGTH = 3000; export const USER_ONLINE_THRESHOLD = 1000 * 60 * 10; // 10min export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days +export const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16; + //#region hard limits // If you change DB_* values, you must also change the DB schema. diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts index 42e5931212..7d030f2f16 100644 --- a/packages/backend/src/core/AbuseReportNotificationService.ts +++ b/packages/backend/src/core/AbuseReportNotificationService.ts @@ -14,37 +14,43 @@ import type { AbuseReportNotificationRecipientRepository, MiAbuseReportNotificationRecipient, MiAbuseUserReport, + MiMeta, MiUser, } from '@/models/_.js'; import { EmailService } from '@/core/EmailService.js'; -import { MetaService } from '@/core/MetaService.js'; import { RoleService } from '@/core/RoleService.js'; import { RecipientMethod } from '@/models/AbuseReportNotificationRecipient.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { IdService } from './IdService.js'; @Injectable() export class AbuseReportNotificationService implements OnApplicationShutdown { constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.abuseReportNotificationRecipientRepository) private abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository, + @Inject(DI.redisForSub) private redisForSub: Redis.Redis, + private idService: IdService, private roleService: RoleService, private systemWebhookService: SystemWebhookService, private emailService: EmailService, - private metaService: MetaService, private moderationLogService: ModerationLogService, private globalEventService: GlobalEventService, + private userEntityService: UserEntityService, ) { this.redisForSub.on('message', this.onMessage); } /** * 管理者用Redisイベントを用いて{@link abuseReports}の内容を管理者各位に通知する. - * 通知先ユーザは{@link RoleService.getModeratorIds}の取得結果に依る. + * 通知先ユーザは{@link getModeratorIds}の取得結果に依る. * * @see RoleService.getModeratorIds * @see GlobalEventService.publishAdminStream @@ -55,7 +61,10 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { return; } - const moderatorIds = await this.roleService.getModeratorIds(true, true); + const moderatorIds = await this.roleService.getModeratorIds({ + includeAdmins: true, + excludeExpire: true, + }); for (const moderatorId of moderatorIds) { for (const abuseReport of abuseReports) { @@ -93,10 +102,8 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { .filter(x => x != null), ); - // 送信先の鮮度を保つため、毎回取得する - const meta = await this.metaService.fetch(true); recipientEMailAddresses.push( - ...(meta.email ? [meta.email] : []), + ...(this.meta.email ? [this.meta.email] : []), ); if (recipientEMailAddresses.length <= 0) { @@ -133,6 +140,26 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { return; } + const usersMap = await this.userEntityService.packMany( + [ + ...new Set([ + ...abuseReports.map(it => it.reporter ?? it.reporterId), + ...abuseReports.map(it => it.targetUser ?? it.targetUserId), + ...abuseReports.map(it => it.assignee ?? it.assigneeId), + ].filter(x => x != null)), + ], + null, + { schema: 'UserLite' }, + ).then(it => new Map(it.map(it => [it.id, it]))); + const convertedReports = abuseReports.map(it => { + return { + ...it, + reporter: usersMap.get(it.reporterId), + targetUser: usersMap.get(it.targetUserId), + assignee: it.assigneeId ? usersMap.get(it.assigneeId) : null, + }; + }); + const recipientWebhookIds = await this.fetchWebhookRecipients() .then(it => it .filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook') @@ -140,7 +167,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { .filter(x => x != null)); for (const webhookId of recipientWebhookIds) { await Promise.all( - abuseReports.map(it => { + convertedReports.map(it => { return this.systemWebhookService.enqueueSystemWebhook( webhookId, type, @@ -346,7 +373,10 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { } // モデレータ権限の有無で通知先設定を振り分ける - const authorizedUserIds = await this.roleService.getModeratorIds(true, true); + const authorizedUserIds = await this.roleService.getModeratorIds({ + includeAdmins: true, + excludeExpire: true, + }); const authorizedUserRecipients = Array.of(); const unauthorizedUserRecipients = Array.of(); for (const recipient of userRecipients) { diff --git a/packages/backend/src/core/AbuseReportService.ts b/packages/backend/src/core/AbuseReportService.ts index 69c51509ba..73baad5499 100644 --- a/packages/backend/src/core/AbuseReportService.ts +++ b/packages/backend/src/core/AbuseReportService.ts @@ -20,8 +20,10 @@ export class AbuseReportService { constructor( @Inject(DI.abuseUserReportsRepository) private abuseUserReportsRepository: AbuseUserReportsRepository, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, + private idService: IdService, private abuseReportNotificationService: AbuseReportNotificationService, private queueService: QueueService, @@ -77,16 +79,16 @@ export class AbuseReportService { * - SystemWebhook * * @param params 通報内容. もし複数件の通報に対応した時のために、あらかじめ複数件を処理できる前提で考える - * @param operator 通報を処理したユーザ + * @param moderator 通報を処理したユーザ * @see AbuseReportNotificationService.notify */ @bindThis public async resolve( params: { reportId: string; - forward: boolean; + resolvedAs: MiAbuseUserReport['resolvedAs']; }[], - operator: MiUser, + moderator: MiUser, ) { const paramsMap = new Map(params.map(it => [it.reportId, it])); const reports = await this.abuseUserReportsRepository.findBy({ @@ -99,25 +101,15 @@ export class AbuseReportService { await this.abuseUserReportsRepository.update(report.id, { resolved: true, - assigneeId: operator.id, - forwarded: ps.forward && report.targetUserHost !== null, + assigneeId: moderator.id, + resolvedAs: ps.resolvedAs, }); - if (ps.forward && report.targetUserHost != null) { - const actor = await this.instanceActorService.getInstanceActor(); - const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); - - // eslint-disable-next-line - const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment); - const contextAssignedFlag = this.apRendererService.addContext(flag); - this.queueService.deliver(actor, contextAssignedFlag, targetUser.inbox, false); - } - this.moderationLogService - .log(operator, 'resolveAbuseReport', { + .log(moderator, 'resolveAbuseReport', { reportId: report.id, report: report, - forwarded: ps.forward && report.targetUserHost !== null, + resolvedAs: ps.resolvedAs, }) .then(); } @@ -125,4 +117,62 @@ export class AbuseReportService { return this.abuseUserReportsRepository.findBy({ id: In(reports.map(it => it.id)) }) .then(reports => this.abuseReportNotificationService.notifySystemWebhook(reports, 'abuseReportResolved')); } + + @bindThis + public async forward( + reportId: MiAbuseUserReport['id'], + moderator: MiUser, + ) { + const report = await this.abuseUserReportsRepository.findOneByOrFail({ id: reportId }); + + if (report.targetUserHost == null) { + throw new Error('The target user host is null.'); + } + + if (report.forwarded) { + throw new Error('The report has already been forwarded.'); + } + + await this.abuseUserReportsRepository.update(report.id, { + forwarded: true, + }); + + const actor = await this.instanceActorService.getInstanceActor(); + const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); + + const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment); + const contextAssignedFlag = this.apRendererService.addContext(flag); + this.queueService.deliver(actor, contextAssignedFlag, targetUser.inbox, false); + + this.moderationLogService + .log(moderator, 'forwardAbuseReport', { + reportId: report.id, + report: report, + }) + .then(); + } + + @bindThis + public async update( + reportId: MiAbuseUserReport['id'], + params: { + moderationNote?: MiAbuseUserReport['moderationNote']; + }, + moderator: MiUser, + ) { + const report = await this.abuseUserReportsRepository.findOneByOrFail({ id: reportId }); + + await this.abuseUserReportsRepository.update(report.id, { + moderationNote: params.moderationNote, + }); + + if (params.moderationNote != null && report.moderationNote !== params.moderationNote) { + this.moderationLogService.log(moderator, 'updateAbuseReportNote', { + reportId: report.id, + report: report, + before: report.moderationNote, + after: params.moderationNote, + }); + } + } } diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index b6b591d240..6e3125044c 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -9,7 +9,7 @@ import { IsNull, In, MoreThan, Not } from 'typeorm'; import { bindThis } from '@/decorators.js'; import { DI } from '@/di-symbols.js'; import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; -import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MutingsRepository, UserListMembershipsRepository, UsersRepository } from '@/models/_.js'; +import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MiMeta, MutingsRepository, UserListMembershipsRepository, UsersRepository } from '@/models/_.js'; import type { RelationshipJobData, ThinUser } from '@/queue/types.js'; import { IdService } from '@/core/IdService.js'; @@ -22,13 +22,15 @@ import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; -import { MetaService } from '@/core/MetaService.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; @Injectable() export class AccountMoveService { constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -57,7 +59,6 @@ export class AccountMoveService { private perUserFollowingChart: PerUserFollowingChart, private federatedInstanceService: FederatedInstanceService, private instanceChart: InstanceChart, - private metaService: MetaService, private relayService: RelayService, private queueService: QueueService, ) { @@ -276,7 +277,7 @@ export class AccountMoveService { if (this.userEntityService.isRemoteUser(oldAccount)) { this.federatedInstanceService.fetch(oldAccount.host).then(async i => { this.instancesRepository.decrement({ id: i.id }, 'followersCount', localFollowerIds.length); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateFollowers(i.host, false); } }); diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 793d8974b3..e827ffa68c 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -123,11 +123,14 @@ export class AntennaService implements OnApplicationShutdown { if (antenna.src === 'home') { // TODO } else if (antenna.src === 'list') { - const listUsers = (await this.userListMembershipsRepository.findBy({ - userListId: antenna.userListId!, - })).map(x => x.userId); - - if (!listUsers.includes(note.userId)) return false; + if (antenna.userListId == null) return false; + const exists = await this.userListMembershipsRepository.exists({ + where: { + userListId: antenna.userListId, + userId: note.userId, + }, + }); + if (!exists) return false; } else if (antenna.src === 'users') { const accts = antenna.users.map(x => { const { username, host } = Acct.parse(x); diff --git a/packages/backend/src/core/AvatarDecorationService.ts b/packages/backend/src/core/AvatarDecorationService.ts index 8b54bbe012..4efd6122b1 100644 --- a/packages/backend/src/core/AvatarDecorationService.ts +++ b/packages/backend/src/core/AvatarDecorationService.ts @@ -29,7 +29,7 @@ export class AvatarDecorationService implements OnApplicationShutdown { private moderationLogService: ModerationLogService, private globalEventService: GlobalEventService, ) { - this.cache = new MemorySingleCache(1000 * 60 * 30); + this.cache = new MemorySingleCache(1000 * 60 * 30); // 30s this.redisForSub.on('message', this.onMessage); } diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index d008e7ec52..6725ebe75b 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -56,10 +56,10 @@ export class CacheService implements OnApplicationShutdown { ) { //this.onMessage = this.onMessage.bind(this); - this.userByIdCache = new MemoryKVCache(Infinity); - this.localUserByNativeTokenCache = new MemoryKVCache(Infinity); - this.localUserByIdCache = new MemoryKVCache(Infinity); - this.uriPersonCache = new MemoryKVCache(Infinity); + this.userByIdCache = new MemoryKVCache(1000 * 60 * 5); // 5m + this.localUserByNativeTokenCache = new MemoryKVCache(1000 * 60 * 5); // 5m + this.localUserByIdCache = new MemoryKVCache(1000 * 60 * 5); // 5m + this.uriPersonCache = new MemoryKVCache(1000 * 60 * 5); // 5m this.userProfileCache = new RedisKVCache(this.redisClient, 'userProfile', { lifetime: 1000 * 60 * 30, // 30m @@ -135,14 +135,14 @@ export class CacheService implements OnApplicationShutdown { if (user == null) { this.userByIdCache.delete(body.id); this.localUserByIdCache.delete(body.id); - for (const [k, v] of this.uriPersonCache.cache.entries()) { + for (const [k, v] of this.uriPersonCache.entries) { if (v.value?.id === body.id) { this.uriPersonCache.delete(k); } } } else { this.userByIdCache.set(user.id, user); - for (const [k, v] of this.uriPersonCache.cache.entries()) { + for (const [k, v] of this.uriPersonCache.entries) { if (v.value?.id === user.id) { this.uriPersonCache.set(k, user); } diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts index f6b7955cd2..206d0dbe0a 100644 --- a/packages/backend/src/core/CaptchaService.ts +++ b/packages/backend/src/core/CaptchaService.ts @@ -119,5 +119,18 @@ export class CaptchaService { throw new Error(`turnstile-failed: ${errorCodes}`); } } + + @bindThis + public async verifyTestcaptcha(response: string | null | undefined): Promise { + if (response == null) { + throw new Error('testcaptcha-failed: no response provided'); + } + + const success = response === 'testcaptcha-passed'; + + if (!success) { + throw new Error('testcaptcha-failed'); + } + } } diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index b5b34487ec..734d135648 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -12,6 +12,9 @@ import { } from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { UserSearchService } from '@/core/UserSearchService.js'; +import { WebhookTestService } from '@/core/WebhookTestService.js'; +import { FlashService } from '@/core/FlashService.js'; import { AccountMoveService } from './AccountMoveService.js'; import { AccountUpdateService } from './AccountUpdateService.js'; import { AiService } from './AiService.js'; @@ -48,6 +51,7 @@ import { PollService } from './PollService.js'; import { PushNotificationService } from './PushNotificationService.js'; import { QueryService } from './QueryService.js'; import { ReactionService } from './ReactionService.js'; +import { ReactionsBufferingService } from './ReactionsBufferingService.js'; import { RelayService } from './RelayService.js'; import { RoleService } from './RoleService.js'; import { S3Service } from './S3Service.js'; @@ -60,6 +64,7 @@ import { UserFollowingService } from './UserFollowingService.js'; import { UserKeypairService } from './UserKeypairService.js'; import { UserListService } from './UserListService.js'; import { UserMutingService } from './UserMutingService.js'; +import { UserRenoteMutingService } from './UserRenoteMutingService.js'; import { UserSuspendService } from './UserSuspendService.js'; import { UserAuthService } from './UserAuthService.js'; import { VideoProcessingService } from './VideoProcessingService.js'; @@ -190,6 +195,7 @@ const $ProxyAccountService: Provider = { provide: 'ProxyAccountService', useExis const $PushNotificationService: Provider = { provide: 'PushNotificationService', useExisting: PushNotificationService }; const $QueryService: Provider = { provide: 'QueryService', useExisting: QueryService }; const $ReactionService: Provider = { provide: 'ReactionService', useExisting: ReactionService }; +const $ReactionsBufferingService: Provider = { provide: 'ReactionsBufferingService', useExisting: ReactionsBufferingService }; const $RelayService: Provider = { provide: 'RelayService', useExisting: RelayService }; const $RoleService: Provider = { provide: 'RoleService', useExisting: RoleService }; const $S3Service: Provider = { provide: 'S3Service', useExisting: S3Service }; @@ -202,13 +208,17 @@ const $UserFollowingService: Provider = { provide: 'UserFollowingService', useEx const $UserKeypairService: Provider = { provide: 'UserKeypairService', useExisting: UserKeypairService }; const $UserListService: Provider = { provide: 'UserListService', useExisting: UserListService }; const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting: UserMutingService }; +const $UserRenoteMutingService: Provider = { provide: 'UserRenoteMutingService', useExisting: UserRenoteMutingService }; +const $UserSearchService: Provider = { provide: 'UserSearchService', useExisting: UserSearchService }; const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; const $UserAuthService: Provider = { provide: 'UserAuthService', useExisting: UserAuthService }; const $VideoProcessingService: Provider = { provide: 'VideoProcessingService', useExisting: VideoProcessingService }; const $UserWebhookService: Provider = { provide: 'UserWebhookService', useExisting: UserWebhookService }; const $SystemWebhookService: Provider = { provide: 'SystemWebhookService', useExisting: SystemWebhookService }; +const $WebhookTestService: Provider = { provide: 'WebhookTestService', useExisting: WebhookTestService }; const $UtilityService: Provider = { provide: 'UtilityService', useExisting: UtilityService }; const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: FileInfoService }; +const $FlashService: Provider = { provide: 'FlashService', useExisting: FlashService }; const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService }; const $ClipService: Provider = { provide: 'ClipService', useExisting: ClipService }; const $FeaturedService: Provider = { provide: 'FeaturedService', useExisting: FeaturedService }; @@ -336,6 +346,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting PushNotificationService, QueryService, ReactionService, + ReactionsBufferingService, RelayService, RoleService, S3Service, @@ -348,13 +359,17 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserKeypairService, UserListService, UserMutingService, + UserRenoteMutingService, + UserSearchService, UserSuspendService, UserAuthService, VideoProcessingService, UserWebhookService, SystemWebhookService, + WebhookTestService, UtilityService, FileInfoService, + FlashService, SearchService, ClipService, FeaturedService, @@ -478,6 +493,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $PushNotificationService, $QueryService, $ReactionService, + $ReactionsBufferingService, $RelayService, $RoleService, $S3Service, @@ -490,13 +506,17 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserKeypairService, $UserListService, $UserMutingService, + $UserRenoteMutingService, + $UserSearchService, $UserSuspendService, $UserAuthService, $VideoProcessingService, $UserWebhookService, $SystemWebhookService, + $WebhookTestService, $UtilityService, $FileInfoService, + $FlashService, $SearchService, $ClipService, $FeaturedService, @@ -621,6 +641,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting PushNotificationService, QueryService, ReactionService, + ReactionsBufferingService, RelayService, RoleService, S3Service, @@ -633,13 +654,17 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserKeypairService, UserListService, UserMutingService, + UserRenoteMutingService, + UserSearchService, UserSuspendService, UserAuthService, VideoProcessingService, UserWebhookService, SystemWebhookService, + WebhookTestService, UtilityService, FileInfoService, + FlashService, SearchService, ClipService, FeaturedService, @@ -762,6 +787,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $PushNotificationService, $QueryService, $ReactionService, + $ReactionsBufferingService, $RelayService, $RoleService, $S3Service, @@ -774,11 +800,14 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserKeypairService, $UserListService, $UserMutingService, + $UserRenoteMutingService, + $UserSearchService, $UserSuspendService, $UserAuthService, $VideoProcessingService, $UserWebhookService, $SystemWebhookService, + $WebhookTestService, $UtilityService, $FileInfoService, $SearchService, diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 7e11b9cdca..4566113449 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -24,7 +24,7 @@ const parseEmojiStrRegexp = /^([-\w]+)(?:@([\w.-]+))?$/; @Injectable() export class CustomEmojiService implements OnApplicationShutdown { - private cache: MemoryKVCache; + private emojisCache: MemoryKVCache; public localEmojisCache: RedisSingleCache>; constructor( @@ -40,7 +40,7 @@ export class CustomEmojiService implements OnApplicationShutdown { private moderationLogService: ModerationLogService, private globalEventService: GlobalEventService, ) { - this.cache = new MemoryKVCache(1000 * 60 * 60 * 12); + this.emojisCache = new MemoryKVCache(1000 * 60 * 60 * 12); // 12h this.localEmojisCache = new RedisSingleCache>(this.redisClient, 'localEmojis', { lifetime: 1000 * 60 * 30, // 30m @@ -103,19 +103,33 @@ export class CustomEmojiService implements OnApplicationShutdown { } @bindThis - public async update(id: MiEmoji['id'], data: { + public async update(data: ( + { id: MiEmoji['id'], name?: string; } | { name: string; id?: MiEmoji['id'], } + ) & { driveFile?: MiDriveFile; - name?: string; category?: string | null; aliases?: string[]; license?: string | null; isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][]; - }, moderator?: MiUser): Promise { - const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); - const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() }); - if (sameNameEmoji != null && sameNameEmoji.id !== id) throw new Error('name already exists'); + }, moderator?: MiUser): Promise< + null + | 'NO_SUCH_EMOJI' + | 'SAME_NAME_EMOJI_EXISTS' + > { + const emoji = data.id + ? await this.getEmojiById(data.id) + : await this.getEmojiByName(data.name!); + if (emoji === null) return 'NO_SUCH_EMOJI'; + const id = emoji.id; + + // IDと絵文字名が両方指定されている場合は絵文字名の変更を行うため重複チェックが必要 + const doNameUpdate = data.id && data.name && (data.name !== emoji.name); + if (doNameUpdate) { + const isDuplicate = await this.checkDuplicate(data.name!); + if (isDuplicate) return 'SAME_NAME_EMOJI_EXISTS'; + } await this.emojisRepository.update(emoji.id, { updatedAt: new Date(), @@ -135,7 +149,7 @@ export class CustomEmojiService implements OnApplicationShutdown { const packed = await this.emojiEntityService.packDetailed(emoji.id); - if (emoji.name === data.name) { + if (!doNameUpdate) { this.globalEventService.publishBroadcastStream('emojiUpdated', { emojis: [packed], }); @@ -157,6 +171,7 @@ export class CustomEmojiService implements OnApplicationShutdown { after: updated, }); } + return null; } @bindThis @@ -334,7 +349,7 @@ export class CustomEmojiService implements OnApplicationShutdown { host, })) ?? null; - const emoji = await this.cache.fetch(`${name} ${host}`, queryOrNull); + const emoji = await this.emojisCache.fetch(`${name} ${host}`, queryOrNull); if (emoji == null) return null; return emoji.publicUrl || emoji.originalUrl; // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ) @@ -361,7 +376,7 @@ export class CustomEmojiService implements OnApplicationShutdown { */ @bindThis public async prefetchEmojis(emojis: { name: string; host: string | null; }[]): Promise { - const notCachedEmojis = emojis.filter(emoji => this.cache.get(`${emoji.name} ${emoji.host}`) == null); + const notCachedEmojis = emojis.filter(emoji => this.emojisCache.get(`${emoji.name} ${emoji.host}`) == null); const emojisQuery: any[] = []; const hosts = new Set(notCachedEmojis.map(e => e.host)); for (const host of hosts) { @@ -376,7 +391,7 @@ export class CustomEmojiService implements OnApplicationShutdown { select: ['name', 'host', 'originalUrl', 'publicUrl'], }) : []; for (const emoji of _emojis) { - this.cache.set(`${emoji.name} ${emoji.host}`, emoji); + this.emojisCache.set(`${emoji.name} ${emoji.host}`, emoji); } } @@ -401,7 +416,7 @@ export class CustomEmojiService implements OnApplicationShutdown { @bindThis public dispose(): void { - this.cache.dispose(); + this.emojisCache.dispose(); } @bindThis diff --git a/packages/backend/src/core/DeleteAccountService.ts b/packages/backend/src/core/DeleteAccountService.ts index 79b614edba..7f1b8f3efb 100644 --- a/packages/backend/src/core/DeleteAccountService.ts +++ b/packages/backend/src/core/DeleteAccountService.ts @@ -4,12 +4,15 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/_.js'; +import { Not, IsNull } from 'typeorm'; +import type { FollowingsRepository, MiUser, UsersRepository } from '@/models/_.js'; import { QueueService } from '@/core/QueueService.js'; -import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; @Injectable() export class DeleteAccountService { @@ -17,9 +20,14 @@ export class DeleteAccountService { @Inject(DI.usersRepository) private usersRepository: UsersRepository, - private userSuspendService: UserSuspendService, + @Inject(DI.followingsRepository) + private followingsRepository: FollowingsRepository, + + private userEntityService: UserEntityService, + private apRendererService: ApRendererService, private queueService: QueueService, private globalEventService: GlobalEventService, + private moderationLogService: ModerationLogService, ) { } @@ -27,16 +35,52 @@ export class DeleteAccountService { public async deleteAccount(user: { id: string; host: string | null; - }): Promise { + }, moderator?: MiUser): Promise { const _user = await this.usersRepository.findOneByOrFail({ id: user.id }); if (_user.isRoot) throw new Error('cannot delete a root account'); - // 物理削除する前にDelete activityを送信する - await this.userSuspendService.doPostSuspend(user).catch(e => {}); + if (moderator != null) { + this.moderationLogService.log(moderator, 'deleteAccount', { + userId: user.id, + userUsername: _user.username, + userHost: user.host, + }); + } - this.queueService.createDeleteAccountJob(user, { - soft: false, - }); + // 物理削除する前にDelete activityを送信する + if (this.userEntityService.isLocalUser(user)) { + // 知り得る全SharedInboxにDelete配信 + const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.userEntityService.genLocalUserUri(user.id), user)); + + const queue: string[] = []; + + const followings = await this.followingsRepository.find({ + where: [ + { followerSharedInbox: Not(IsNull()) }, + { followeeSharedInbox: Not(IsNull()) }, + ], + select: ['followerSharedInbox', 'followeeSharedInbox'], + }); + + const inboxes = followings.map(x => x.followerSharedInbox ?? x.followeeSharedInbox); + + for (const inbox of inboxes) { + if (inbox != null && !queue.includes(inbox)) queue.push(inbox); + } + + for (const inbox of queue) { + this.queueService.deliver(user, content, inbox, true); + } + + this.queueService.createDeleteAccountJob(user, { + soft: false, + }); + } else { + // リモートユーザーの削除は、完全にDBから物理削除してしまうと再度連合してきてアカウントが復活する可能性があるため、soft指定する + this.queueService.createDeleteAccountJob(user, { + soft: true, + }); + } await this.usersRepository.update(user.id, { isDeleted: true, diff --git a/packages/backend/src/core/DownloadService.ts b/packages/backend/src/core/DownloadService.ts index 21ae798f9f..93f4a38246 100644 --- a/packages/backend/src/core/DownloadService.ts +++ b/packages/backend/src/core/DownloadService.ts @@ -42,7 +42,7 @@ export class DownloadService { const timeout = 30 * 1000; const operationTimeout = 60 * 1000; - const maxSize = this.config.maxFileSize ?? 262144000; + const maxSize = this.config.maxFileSize; const urlObj = new URL(url); let filename = urlObj.pathname.split('/').pop() ?? 'untitled'; diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 37c5d1adf7..c332e5a0a8 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -11,11 +11,10 @@ import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; import { IsNull } from 'typeorm'; import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/_.js'; +import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository, MiMeta } from '@/models/_.js'; import type { Config } from '@/config.js'; import Logger from '@/logger.js'; import type { MiRemoteUser, MiUser } from '@/models/User.js'; -import { MetaService } from '@/core/MetaService.js'; import { MiDriveFile } from '@/models/DriveFile.js'; import { IdService } from '@/core/IdService.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; @@ -43,6 +42,7 @@ import { RoleService } from '@/core/RoleService.js'; import { correctFilename } from '@/misc/correct-filename.js'; import { isMimeImage } from '@/misc/is-mime-image.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { UtilityService } from '@/core/UtilityService.js'; type AddFileArgs = { /** User who wish to add file */ @@ -98,6 +98,9 @@ export class DriveService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -114,7 +117,6 @@ export class DriveService { private userEntityService: UserEntityService, private driveFileEntityService: DriveFileEntityService, private idService: IdService, - private metaService: MetaService, private downloadService: DownloadService, private internalStorageService: InternalStorageService, private s3Service: S3Service, @@ -127,6 +129,7 @@ export class DriveService { private driveChart: DriveChart, private perUserDriveChart: PerUserDriveChart, private instanceChart: InstanceChart, + private utilityService: UtilityService, ) { const logger = new Logger('drive', 'blue'); this.registerLogger = logger.createSubLogger('register', 'yellow'); @@ -147,9 +150,7 @@ export class DriveService { // thunbnail, webpublic を必要なら生成 const alts = await this.generateAlts(path, type, !file.uri); - const meta = await this.metaService.fetch(); - - if (meta.useObjectStorage) { + if (this.meta.useObjectStorage) { //#region ObjectStorage params let [ext] = (name.match(/\.([a-zA-Z0-9_-]+)$/) ?? ['']); @@ -168,11 +169,11 @@ export class DriveService { ext = ''; } - const baseUrl = meta.objectStorageBaseUrl - ?? `${ meta.objectStorageUseSSL ? 'https' : 'http' }://${ meta.objectStorageEndpoint }${ meta.objectStoragePort ? `:${meta.objectStoragePort}` : '' }/${ meta.objectStorageBucket }`; + const baseUrl = this.meta.objectStorageBaseUrl + ?? `${ this.meta.objectStorageUseSSL ? 'https' : 'http' }://${ this.meta.objectStorageEndpoint }${ this.meta.objectStoragePort ? `:${this.meta.objectStoragePort}` : '' }/${ this.meta.objectStorageBucket }`; // for original - const key = `${meta.objectStoragePrefix}/${randomUUID()}${ext}`; + const key = `${this.meta.objectStoragePrefix}/${randomUUID()}${ext}`; const url = `${ baseUrl }/${ key }`; // for alts @@ -189,7 +190,7 @@ export class DriveService { ]; if (alts.webpublic) { - webpublicKey = `${meta.objectStoragePrefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`; + webpublicKey = `${this.meta.objectStoragePrefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`; webpublicUrl = `${ baseUrl }/${ webpublicKey }`; this.registerLogger.info(`uploading webpublic: ${webpublicKey}`); @@ -197,7 +198,7 @@ export class DriveService { } if (alts.thumbnail) { - thumbnailKey = `${meta.objectStoragePrefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`; + thumbnailKey = `${this.meta.objectStoragePrefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`; thumbnailUrl = `${ baseUrl }/${ thumbnailKey }`; this.registerLogger.info(`uploading thumbnail: ${thumbnailKey}`); @@ -374,10 +375,8 @@ export class DriveService { if (type === 'image/apng') type = 'image/png'; if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream'; - const meta = await this.metaService.fetch(); - const params = { - Bucket: meta.objectStorageBucket, + Bucket: this.meta.objectStorageBucket, Key: key, Body: stream, ContentType: type, @@ -390,9 +389,9 @@ export class DriveService { // 許可されているファイル形式でしか拡張子をつけない ext ? correctFilename(filename, ext) : filename, ); - if (meta.objectStorageSetPublicRead) params.ACL = 'public-read'; + if (this.meta.objectStorageSetPublicRead) params.ACL = 'public-read'; - await this.s3Service.upload(meta, params) + await this.s3Service.upload(this.meta, params) .then( result => { if ('Bucket' in result) { // CompleteMultipartUploadCommandOutput @@ -458,32 +457,31 @@ export class DriveService { ext = null, }: AddFileArgs): Promise { let skipNsfwCheck = false; - const instance = await this.metaService.fetch(); const userRoleNSFW = user && (await this.roleService.getUserPolicies(user.id)).alwaysMarkNsfw; if (user == null) { skipNsfwCheck = true; } else if (userRoleNSFW) { skipNsfwCheck = true; } - if (instance.sensitiveMediaDetection === 'none') skipNsfwCheck = true; - if (user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)) skipNsfwCheck = true; - if (user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)) skipNsfwCheck = true; + if (this.meta.sensitiveMediaDetection === 'none') skipNsfwCheck = true; + if (user && this.meta.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)) skipNsfwCheck = true; + if (user && this.meta.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)) skipNsfwCheck = true; const info = await this.fileInfoService.getFileInfo(path, { skipSensitiveDetection: skipNsfwCheck, sensitiveThreshold: // 感度が高いほどしきい値は低くすることになる - instance.sensitiveMediaDetectionSensitivity === 'veryHigh' ? 0.1 : - instance.sensitiveMediaDetectionSensitivity === 'high' ? 0.3 : - instance.sensitiveMediaDetectionSensitivity === 'low' ? 0.7 : - instance.sensitiveMediaDetectionSensitivity === 'veryLow' ? 0.9 : + this.meta.sensitiveMediaDetectionSensitivity === 'veryHigh' ? 0.1 : + this.meta.sensitiveMediaDetectionSensitivity === 'high' ? 0.3 : + this.meta.sensitiveMediaDetectionSensitivity === 'low' ? 0.7 : + this.meta.sensitiveMediaDetectionSensitivity === 'veryLow' ? 0.9 : 0.5, sensitiveThresholdForPorn: 0.75, - enableSensitiveMediaDetectionForVideos: instance.enableSensitiveMediaDetectionForVideos, + enableSensitiveMediaDetectionForVideos: this.meta.enableSensitiveMediaDetectionForVideos, }); this.registerLogger.info(`${JSON.stringify(info)}`); // 現状 false positive が多すぎて実用に耐えない - //if (info.porn && instance.disallowUploadWhenPredictedAsPorn) { + //if (info.porn && this.meta.disallowUploadWhenPredictedAsPorn) { // throw new IdentifiableError('282f77bf-5816-4f72-9264-aa14d8261a21', 'Detected as porn.'); //} @@ -587,8 +585,9 @@ export class DriveService { sensitive ?? false : false; + if (user && this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) file.isSensitive = true; if (info.sensitive && profile!.autoSensitive) file.isSensitive = true; - if (info.sensitive && instance.setSensitiveFlagAutomatically) file.isSensitive = true; + if (info.sensitive && this.meta.setSensitiveFlagAutomatically) file.isSensitive = true; if (userRoleNSFW) file.isSensitive = true; if (url !== null) { @@ -649,7 +648,7 @@ export class DriveService { // ローカルユーザーのみ this.perUserDriveChart.update(file, true); } else { - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateDrive(file, true); } } @@ -795,7 +794,7 @@ export class DriveService { // ローカルユーザーのみ this.perUserDriveChart.update(file, false); } else { - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateDrive(file, false); } } @@ -817,14 +816,13 @@ export class DriveService { @bindThis public async deleteObjectStorageFile(key: string) { - const meta = await this.metaService.fetch(); try { const param = { - Bucket: meta.objectStorageBucket, + Bucket: this.meta.objectStorageBucket, Key: key, } as DeleteObjectCommandInput; - await this.s3Service.delete(meta, param); + await this.s3Service.delete(this.meta, param); } catch (err: any) { if (err.name === 'NoSuchKey') { this.deleteLogger.warn(`The object storage had no such key to delete: ${key}. Skipping this.`, err as Error); diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 435dbbae28..a176474b95 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -5,18 +5,17 @@ import { URLSearchParams } from 'node:url'; import * as nodemailer from 'nodemailer'; +import juice from 'juice'; import { Inject, Injectable } from '@nestjs/common'; import { validate as validateEmail } from 'deep-email-validator'; -import { MetaService } from '@/core/MetaService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; -import type { UserProfilesRepository } from '@/models/_.js'; +import type { MiMeta, UserProfilesRepository } from '@/models/_.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; -import { QueueService } from '@/core/QueueService.js'; @Injectable() export class EmailService { @@ -26,49 +25,41 @@ export class EmailService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, - private metaService: MetaService, private loggerService: LoggerService, private utilityService: UtilityService, private httpRequestService: HttpRequestService, - private queueService: QueueService, ) { this.logger = this.loggerService.getLogger('email'); } @bindThis public async sendEmail(to: string, subject: string, html: string, text: string) { - const meta = await this.metaService.fetch(true); - - if (!meta.enableEmail) return; + if (!this.meta.enableEmail) return; const iconUrl = `${this.config.url}/static-assets/mi-white.png`; const emailSettingUrl = `${this.config.url}/settings/email`; - const enableAuth = meta.smtpUser != null && meta.smtpUser !== ''; + const enableAuth = this.meta.smtpUser != null && this.meta.smtpUser !== ''; const transporter = nodemailer.createTransport({ - host: meta.smtpHost, - port: meta.smtpPort, - secure: meta.smtpSecure, + host: this.meta.smtpHost, + port: this.meta.smtpPort, + secure: this.meta.smtpSecure, ignoreTLS: !enableAuth, proxy: this.config.proxySmtp, auth: enableAuth ? { - user: meta.smtpUser, - pass: meta.smtpPass, + user: this.meta.smtpUser, + pass: this.meta.smtpPass, } : undefined, } as any); - try { - // TODO: htmlサニタイズ - const info = await transporter.sendMail({ - from: meta.email!, - to: to, - subject: subject, - text: text, - html: ` + const htmlContent = ` @@ -133,7 +124,7 @@ export class EmailService {
- +

${ subject }

@@ -147,7 +138,18 @@ export class EmailService { ${ this.config.host } -`, +`; + + const inlinedHtml = juice(htmlContent); + + try { + // TODO: htmlサニタイズ + const info = await transporter.sendMail({ + from: this.meta.email!, + to: to, + subject: subject, + text: text, + html: inlinedHtml, }); this.logger.info(`Message sent: ${info.messageId}`); @@ -162,8 +164,6 @@ export class EmailService { available: boolean; reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist'; }> { - const meta = await this.metaService.fetch(); - const exist = await this.userProfilesRepository.countBy({ emailVerified: true, email: emailAddress, @@ -181,11 +181,11 @@ export class EmailService { reason?: string | null, } = { valid: true, reason: null }; - if (meta.enableActiveEmailValidation) { - if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) { - validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey); - } else if (meta.enableTruemailApi && meta.truemailInstance && meta.truemailAuthKey != null) { - validated = await this.trueMail(meta.truemailInstance, emailAddress, meta.truemailAuthKey); + if (this.meta.enableActiveEmailValidation) { + if (this.meta.enableVerifymailApi && this.meta.verifymailAuthKey != null) { + validated = await this.verifyMail(emailAddress, this.meta.verifymailAuthKey); + } else if (this.meta.enableTruemailApi && this.meta.truemailInstance && this.meta.truemailAuthKey != null) { + validated = await this.trueMail(this.meta.truemailInstance, emailAddress, this.meta.truemailAuthKey); } else { validated = await validateEmail({ email: emailAddress, @@ -215,7 +215,7 @@ export class EmailService { } const emailDomain: string = emailAddress.split('@')[1]; - const isBanned = this.utilityService.isBlockedHost(meta.bannedEmailDomains, emailDomain); + const isBanned = this.utilityService.isBlockedHost(this.meta.bannedEmailDomains, emailDomain); if (isBanned) { return { diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts index 6799f2c5bb..7aeeb78178 100644 --- a/packages/backend/src/core/FederatedInstanceService.ts +++ b/packages/backend/src/core/FederatedInstanceService.ts @@ -40,6 +40,7 @@ export class FederatedInstanceService implements OnApplicationShutdown { firstRetrievedAt: new Date(parsed.firstRetrievedAt), latestRequestReceivedAt: parsed.latestRequestReceivedAt ? new Date(parsed.latestRequestReceivedAt) : null, infoUpdatedAt: parsed.infoUpdatedAt ? new Date(parsed.infoUpdatedAt) : null, + notRespondingSince: parsed.notRespondingSince ? new Date(parsed.notRespondingSince) : null, }; }, }); diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts index 169285f033..6bd6cb8d9b 100644 --- a/packages/backend/src/core/FileInfoService.ts +++ b/packages/backend/src/core/FileInfoService.ts @@ -15,7 +15,7 @@ import isSvg from 'is-svg'; import probeImageSize from 'probe-image-size'; import { type predictionType } from 'nsfwjs'; import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; -import { encode } from 'blurhash'; +import * as blurhash from 'blurhash'; import { createTempDir } from '@/misc/create-temp.js'; import { AiService } from '@/core/AiService.js'; import { LoggerService } from '@/core/LoggerService.js'; @@ -452,7 +452,7 @@ export class FileInfoService { } /** - * Calculate average color of image + * Calculate blurhash string of image */ @bindThis private getBlurhash(path: string, type: string): Promise { @@ -467,7 +467,7 @@ export class FileInfoService { let hash; try { - hash = encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5); + hash = blurhash.encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5); } catch (e) { return reject(e); } diff --git a/packages/backend/src/core/FlashService.ts b/packages/backend/src/core/FlashService.ts new file mode 100644 index 0000000000..2a98225382 --- /dev/null +++ b/packages/backend/src/core/FlashService.ts @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import { type FlashsRepository } from '@/models/_.js'; + +/** + * MisskeyPlay関係のService + */ +@Injectable() +export class FlashService { + constructor( + @Inject(DI.flashsRepository) + private flashRepository: FlashsRepository, + ) { + } + + /** + * 人気のあるPlay一覧を取得する. + */ + public async featured(opts?: { offset?: number, limit: number }) { + const builder = this.flashRepository.createQueryBuilder('flash') + .andWhere('flash.likedCount > 0') + .andWhere('flash.visibility = :visibility', { visibility: 'public' }) + .addOrderBy('flash.likedCount', 'DESC') + .addOrderBy('flash.updatedAt', 'DESC') + .addOrderBy('flash.id', 'DESC'); + + if (opts?.offset) { + builder.skip(opts.offset); + } + + builder.take(opts?.limit ?? 10); + + return await builder.getMany(); + } +} diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index a70743bed2..03646ff566 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -209,6 +209,10 @@ type SerializedAll = { [K in keyof T]: Serialized; }; +type UndefinedAsNullAll = { + [K in keyof T]: T[K] extends undefined ? null : T[K]; +} + export interface InternalEventTypes { userChangeSuspendedState: { id: MiUser['id']; isSuspended: MiUser['isSuspended']; }; userChangeDeletedState: { id: MiUser['id']; isDeleted: MiUser['isDeleted']; }; @@ -237,7 +241,7 @@ export interface InternalEventTypes { avatarDecorationCreated: MiAvatarDecoration; avatarDecorationDeleted: MiAvatarDecoration; avatarDecorationUpdated: MiAvatarDecoration; - metaUpdated: MiMeta; + metaUpdated: { before?: MiMeta; after: MiMeta; }; followChannel: { userId: MiUser['id']; channelId: MiChannel['id']; }; unfollowChannel: { userId: MiUser['id']; channelId: MiChannel['id']; }; updateUserProfile: MiUserProfile; @@ -247,43 +251,45 @@ export interface InternalEventTypes { userListMemberRemoved: { userListId: MiUserList['id']; memberId: MiUser['id']; }; } +type EventTypesToEventPayload = EventUnionFromDictionary>>; + // name/messages(spec) pairs dictionary export type GlobalEvents = { internal: { name: 'internal'; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; broadcast: { name: 'broadcast'; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; main: { name: `mainStream:${MiUser['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; drive: { name: `driveStream:${MiUser['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; note: { name: `noteStream:${MiNote['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; userList: { name: `userListStream:${MiUserList['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; roleTimeline: { name: `roleTimelineStream:${MiRole['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; antenna: { name: `antennaStream:${MiAntenna['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; admin: { name: `adminStream:${MiUser['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; notes: { name: 'notesStream'; @@ -291,11 +297,11 @@ export type GlobalEvents = { }; reversi: { name: `reversiStream:${MiUser['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; reversiGame: { name: `reversiGameStream:${MiReversiGame['id']}`; - payload: EventUnionFromDictionary>; + payload: EventTypesToEventPayload; }; }; diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts index eb192ee6da..793bbeecb1 100644 --- a/packages/backend/src/core/HashtagService.ts +++ b/packages/backend/src/core/HashtagService.ts @@ -10,16 +10,18 @@ import type { MiUser } from '@/models/User.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { IdService } from '@/core/IdService.js'; import type { MiHashtag } from '@/models/Hashtag.js'; -import type { HashtagsRepository } from '@/models/_.js'; +import type { HashtagsRepository, MiMeta } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; import { FeaturedService } from '@/core/FeaturedService.js'; -import { MetaService } from '@/core/MetaService.js'; import { UtilityService } from '@/core/UtilityService.js'; @Injectable() export class HashtagService { constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.redis) private redisClient: Redis.Redis, // TODO: 専用のRedisサーバーを設定できるようにする @@ -29,7 +31,6 @@ export class HashtagService { private userEntityService: UserEntityService, private featuredService: FeaturedService, private idService: IdService, - private metaService: MetaService, private utilityService: UtilityService, ) { } @@ -160,10 +161,9 @@ export class HashtagService { @bindThis public async updateHashtagsRanking(hashtag: string, userId: MiUser['id']): Promise { - const instance = await this.metaService.fetch(); - const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t)); + const hiddenTags = this.meta.hiddenTags.map(t => normalizeForSearch(t)); if (hiddenTags.includes(hashtag)) return; - if (this.utilityService.isKeyWordIncluded(hashtag, instance.sensitiveWords)) return; + if (this.utilityService.isKeyWordIncluded(hashtag, this.meta.sensitiveWords)) return; // YYYYMMDDHHmm (10分間隔) const now = new Date(); diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index ec630f804e..3d88d0aefe 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -52,7 +52,7 @@ export class MetaService implements OnApplicationShutdown { switch (type) { case 'metaUpdated': { this.cache = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, + ...(body.after), proxyAccount: null, // joinなカラムは通常取ってこないので }; break; @@ -141,7 +141,7 @@ export class MetaService implements OnApplicationShutdown { }); } - this.globalEventService.publishInternalEvent('metaUpdated', updated); + this.globalEventService.publishInternalEvent('metaUpdated', { before, after: updated }); return updated; } diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 9786f8b8bb..d33b228c3d 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -13,10 +13,12 @@ import { intersperse } from '@/misc/prelude/array.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; -import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js'; +import type { DefaultTreeAdapterMap } from 'parse5'; import type * as mfm from 'mfm-js'; -const treeAdapter = TreeAdapter.defaultTreeAdapter; +const treeAdapter = parse5.defaultTreeAdapter; +type Node = DefaultTreeAdapterMap['node']; +type ChildNode = DefaultTreeAdapterMap['childNode']; const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; @@ -46,7 +48,7 @@ export class MfmService { return text.trim(); - function getText(node: TreeAdapter.Node): string { + function getText(node: Node): string { if (treeAdapter.isTextNode(node)) return node.value; if (!treeAdapter.isElementNode(node)) return ''; if (node.nodeName === 'br') return '\n'; @@ -58,7 +60,7 @@ export class MfmService { return ''; } - function appendChildren(childNodes: TreeAdapter.ChildNode[]): void { + function appendChildren(childNodes: ChildNode[]): void { if (childNodes) { for (const n of childNodes) { analyze(n); @@ -66,14 +68,16 @@ export class MfmService { } } - function analyze(node: TreeAdapter.Node) { + function analyze(node: Node) { if (treeAdapter.isTextNode(node)) { text += node.value; return; } // Skip comment or document type node - if (!treeAdapter.isElementNode(node)) return; + if (!treeAdapter.isElementNode(node)) { + return; + } switch (node.nodeName) { case 'br': { @@ -81,8 +85,7 @@ export class MfmService { break; } - case 'a': - { + case 'a': { const txt = getText(node); const rel = node.attrs.find(x => x.name === 'rel'); const href = node.attrs.find(x => x.name === 'href'); @@ -90,7 +93,7 @@ export class MfmService { // ハッシュタグ if (normalizedHashtagNames && href && normalizedHashtagNames.has(normalizeForSearch(txt))) { text += txt; - // メンション + // メンション } else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) { const part = txt.split('@'); @@ -102,7 +105,7 @@ export class MfmService { } else if (part.length === 3) { text += txt; } - // その他 + // その他 } else { const generateLink = () => { if (!href && !txt) { @@ -130,8 +133,7 @@ export class MfmService { break; } - case 'h1': - { + case 'h1': { text += '【'; appendChildren(node.childNodes); text += '】\n'; @@ -139,16 +141,14 @@ export class MfmService { } case 'b': - case 'strong': - { + case 'strong': { text += '**'; appendChildren(node.childNodes); text += '**'; break; } - case 'small': - { + case 'small': { text += ''; appendChildren(node.childNodes); text += ''; @@ -156,8 +156,7 @@ export class MfmService { } case 's': - case 'del': - { + case 'del': { text += '~~'; appendChildren(node.childNodes); text += '~~'; @@ -165,8 +164,7 @@ export class MfmService { } case 'i': - case 'em': - { + case 'em': { text += ''; appendChildren(node.childNodes); text += ''; @@ -207,8 +205,7 @@ export class MfmService { case 'h3': case 'h4': case 'h5': - case 'h6': - { + case 'h6': { text += '\n\n'; appendChildren(node.childNodes); break; @@ -221,8 +218,7 @@ export class MfmService { case 'article': case 'li': case 'dt': - case 'dd': - { + case 'dd': { text += '\n'; appendChildren(node.childNodes); break; @@ -243,7 +239,7 @@ export class MfmService { return null; } - const { window } = new Window(); + const { happyDOM, window } = new Window(); const doc = window.document; @@ -461,6 +457,10 @@ export class MfmService { appendChildren(nodes, body); - return new XMLSerializer().serializeToString(body); + const serialized = new XMLSerializer().serializeToString(body); + + happyDOM.close().catch(err => {}); + + return serialized; } } diff --git a/packages/backend/src/core/ModerationLogService.ts b/packages/backend/src/core/ModerationLogService.ts index 6c155c9a62..2c02af217d 100644 --- a/packages/backend/src/core/ModerationLogService.ts +++ b/packages/backend/src/core/ModerationLogService.ts @@ -9,7 +9,8 @@ import type { ModerationLogsRepository } from '@/models/_.js'; import type { MiUser } from '@/models/User.js'; import { IdService } from '@/core/IdService.js'; import { bindThis } from '@/decorators.js'; -import { ModerationLogPayloads, moderationLogTypes } from '@/types.js'; +import type { ModerationLogPayloads } from '@/types.js'; +import { moderationLogTypes } from '@/types.js'; @Injectable() export class ModerationLogService { diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index a2c3aaa701..0ce57f16e6 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -8,13 +8,12 @@ import * as mfm from 'mfm-js'; import { In, DataSource, IsNull, LessThan } from 'typeorm'; import * as Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; -import RE2 from 're2'; import { extractMentions } from '@/misc/extract-mentions.js'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; import { extractHashtags } from '@/misc/extract-hashtags.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js'; import { MiNote } from '@/models/Note.js'; -import type { ChannelFollowingsRepository, ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserListMembershipsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { ChannelFollowingsRepository, ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, MiMeta, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserListMembershipsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiApp } from '@/models/App.js'; import { concat } from '@/misc/prelude/array.js'; @@ -23,11 +22,8 @@ import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { IPoll } from '@/models/Poll.js'; import { MiPoll } from '@/models/Poll.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; -import { checkWordMute } from '@/misc/check-word-mute.js'; import type { MiChannel } from '@/models/Channel.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; -import { MemorySingleCache } from '@/misc/cache.js'; -import type { MiUserProfile } from '@/models/UserProfile.js'; import { RelayService } from '@/core/RelayService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { DI } from '@/di-symbols.js'; @@ -51,7 +47,6 @@ import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; import { bindThis } from '@/decorators.js'; import { DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { RoleService } from '@/core/RoleService.js'; -import { MetaService } from '@/core/MetaService.js'; import { SearchService } from '@/core/SearchService.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; @@ -60,6 +55,7 @@ import { UserBlockingService } from '@/core/UserBlockingService.js'; import { isReply } from '@/misc/is-reply.js'; import { trackPromise } from '@/misc/promise-tracker.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { CollapsedQueue } from '@/misc/collapsed-queue.js'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; @@ -151,11 +147,15 @@ type Option = { @Injectable() export class NoteCreateService implements OnApplicationShutdown { #shutdownController = new AbortController(); + private updateNotesCountQueue: CollapsedQueue; constructor( @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.db) private db: DataSource, @@ -210,7 +210,6 @@ export class NoteCreateService implements OnApplicationShutdown { private apDeliverManagerService: ApDeliverManagerService, private apRendererService: ApRendererService, private roleService: RoleService, - private metaService: MetaService, private searchService: SearchService, private notesChart: NotesChart, private perUserNotesChart: PerUserNotesChart, @@ -218,7 +217,9 @@ export class NoteCreateService implements OnApplicationShutdown { private instanceChart: InstanceChart, private utilityService: UtilityService, private userBlockingService: UserBlockingService, - ) { } + ) { + this.updateNotesCountQueue = new CollapsedQueue(process.env.NODE_ENV !== 'test' ? 60 * 1000 * 5 : 0, this.collapseNotesCount, this.performUpdateNotesCount); + } @bindThis public async create(user: { @@ -251,10 +252,8 @@ export class NoteCreateService implements OnApplicationShutdown { if (data.channel != null) data.visibleUsers = []; if (data.channel != null) data.localOnly = true; - const meta = await this.metaService.fetch(); - if (data.visibility === 'public' && data.channel == null) { - const sensitiveWords = meta.sensitiveWords; + const sensitiveWords = this.meta.sensitiveWords; if (this.utilityService.isKeyWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) { data.visibility = 'home'; } else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) { @@ -262,17 +261,17 @@ export class NoteCreateService implements OnApplicationShutdown { } } - const hasProhibitedWords = await this.checkProhibitedWordsContain({ + const hasProhibitedWords = this.checkProhibitedWordsContain({ cw: data.cw, text: data.text, pollChoices: data.poll?.choices, - }, meta.prohibitedWords); + }, this.meta.prohibitedWords); if (hasProhibitedWords) { throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Note contains prohibited words'); } - const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host); + const inSilencedInstance = this.utilityService.isSilencedHost(this.meta.silencedHosts, user.host); if (data.visibility === 'public' && inSilencedInstance && user.host !== null) { data.visibility = 'home'; @@ -364,6 +363,9 @@ export class NoteCreateService implements OnApplicationShutdown { mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens); } + // if the host is media-silenced, custom emojis are not allowed + if (this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) emojis = []; + tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32); if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) { @@ -503,18 +505,16 @@ export class NoteCreateService implements OnApplicationShutdown { host: MiUser['host']; isBot: MiUser['isBot']; }, data: Option, silent: boolean, tags: string[], mentionedUsers: MinimumUser[]) { - const meta = await this.metaService.fetch(); - this.notesChart.update(note, true); - if (meta.enableChartsForRemoteUser || (user.host == null)) { + if (note.visibility !== 'specified' && (this.meta.enableChartsForRemoteUser || (user.host == null))) { this.perUserNotesChart.update(user, note, true); } // Register host if (this.userEntityService.isRemoteUser(user)) { this.federatedInstanceService.fetch(user.host).then(async i => { - this.instancesRepository.increment({ id: i.id }, 'notesCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + this.updateNotesCountQueue.enqueue(i.id, 1); + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateNote(i.host, note, true); } }); @@ -850,15 +850,14 @@ export class NoteCreateService implements OnApplicationShutdown { @bindThis private async pushToTl(note: MiNote, user: { id: MiUser['id']; host: MiUser['host']; }) { - const meta = await this.metaService.fetch(); - if (!meta.enableFanoutTimeline) return; + if (!this.meta.enableFanoutTimeline) return; const r = this.redisForTimelines.pipeline(); if (note.channelId) { this.fanoutTimelineService.push(`channelTimeline:${note.channelId}`, note.id, this.config.perChannelMaxNoteCacheCount, r); - this.fanoutTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r); + this.fanoutTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, note.userHost == null ? this.meta.perLocalUserUserTimelineCacheMax : this.meta.perRemoteUserUserTimelineCacheMax, r); const channelFollowings = await this.channelFollowingsRepository.find({ where: { @@ -868,9 +867,9 @@ export class NoteCreateService implements OnApplicationShutdown { }); for (const channelFollowing of channelFollowings) { - this.fanoutTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r); + this.fanoutTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, this.meta.perUserHomeTimelineCacheMax, r); if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r); + this.fanoutTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, this.meta.perUserHomeTimelineCacheMax / 2, r); } } } else { @@ -908,9 +907,9 @@ export class NoteCreateService implements OnApplicationShutdown { if (!following.withReplies) continue; } - this.fanoutTimelineService.push(`homeTimeline:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r); + this.fanoutTimelineService.push(`homeTimeline:${following.followerId}`, note.id, this.meta.perUserHomeTimelineCacheMax, r); if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r); + this.fanoutTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, this.meta.perUserHomeTimelineCacheMax / 2, r); } } @@ -927,22 +926,25 @@ export class NoteCreateService implements OnApplicationShutdown { if (!userListMembership.withReplies) continue; } - this.fanoutTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax, r); + this.fanoutTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, this.meta.perUserListTimelineCacheMax, r); if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax / 2, r); + this.fanoutTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, this.meta.perUserListTimelineCacheMax / 2, r); } } - if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { // 自分自身のHTL - this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r); - if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r); + // 自分自身のHTL + if (note.userHost == null) { + if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { + this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, this.meta.perUserHomeTimelineCacheMax, r); + if (note.fileIds.length > 0) { + this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, this.meta.perUserHomeTimelineCacheMax / 2, r); + } } } // 自分自身以外への返信 if (isReply(note)) { - this.fanoutTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r); + this.fanoutTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, note.userHost == null ? this.meta.perLocalUserUserTimelineCacheMax : this.meta.perRemoteUserUserTimelineCacheMax, r); if (note.visibility === 'public' && note.userHost == null) { this.fanoutTimelineService.push('localTimelineWithReplies', note.id, 300, r); @@ -951,9 +953,9 @@ export class NoteCreateService implements OnApplicationShutdown { } } } else { - this.fanoutTimelineService.push(`userTimeline:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r); + this.fanoutTimelineService.push(`userTimeline:${user.id}`, note.id, note.userHost == null ? this.meta.perLocalUserUserTimelineCacheMax : this.meta.perRemoteUserUserTimelineCacheMax, r); if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r); + this.fanoutTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, note.userHost == null ? this.meta.perLocalUserUserTimelineCacheMax / 2 : this.meta.perRemoteUserUserTimelineCacheMax / 2, r); } if (note.visibility === 'public' && note.userHost == null) { @@ -1012,9 +1014,9 @@ export class NoteCreateService implements OnApplicationShutdown { } } - public async checkProhibitedWordsContain(content: Parameters[0], prohibitedWords?: string[]) { + public checkProhibitedWordsContain(content: Parameters[0], prohibitedWords?: string[]) { if (prohibitedWords == null) { - prohibitedWords = (await this.metaService.fetch()).prohibitedWords; + prohibitedWords = this.meta.prohibitedWords; } if ( @@ -1030,12 +1032,23 @@ export class NoteCreateService implements OnApplicationShutdown { } @bindThis - public dispose(): void { - this.#shutdownController.abort(); + private collapseNotesCount(oldValue: number, newValue: number) { + return oldValue + newValue; } @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); + private async performUpdateNotesCount(id: MiNote['id'], incrBy: number) { + await this.instancesRepository.increment({ id: id }, 'notesCount', incrBy); + } + + @bindThis + public async dispose(): Promise { + this.#shutdownController.abort(); + await this.updateNotesCountQueue.performAllNow(); + } + + @bindThis + public async onApplicationShutdown(signal?: string | undefined): Promise { + await this.dispose(); } } diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts index 801ed02e00..f9f8ace386 100644 --- a/packages/backend/src/core/NoteDeleteService.ts +++ b/packages/backend/src/core/NoteDeleteService.ts @@ -7,7 +7,7 @@ import { Brackets, In } from 'typeorm'; import { Injectable, Inject } from '@nestjs/common'; import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { MiNote, IMentionedRemoteUsers } from '@/models/Note.js'; -import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/_.js'; +import type { InstancesRepository, MiMeta, NotesRepository, UsersRepository } from '@/models/_.js'; import { RelayService } from '@/core/RelayService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { DI } from '@/di-symbols.js'; @@ -19,9 +19,7 @@ import { GlobalEventService } from '@/core/GlobalEventService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; import { SearchService } from '@/core/SearchService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { isQuote, isRenote } from '@/misc/is-renote.js'; @@ -32,6 +30,9 @@ export class NoteDeleteService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -42,13 +43,11 @@ export class NoteDeleteService { private instancesRepository: InstancesRepository, private userEntityService: UserEntityService, - private noteEntityService: NoteEntityService, private globalEventService: GlobalEventService, private relayService: RelayService, private federatedInstanceService: FederatedInstanceService, private apRendererService: ApRendererService, private apDeliverManagerService: ApDeliverManagerService, - private metaService: MetaService, private searchService: SearchService, private moderationLogService: ModerationLogService, private notesChart: NotesChart, @@ -92,7 +91,7 @@ export class NoteDeleteService { this.deliverToConcerned(user, note, content); } - // also deliever delete activity to cascaded notes + // also deliver delete activity to cascaded notes const federatedLocalCascadingNotes = (cascadingNotes).filter(note => !note.localOnly && note.userHost == null); // filter out local-only notes for (const cascadingNote of federatedLocalCascadingNotes) { if (!cascadingNote.user) continue; @@ -102,17 +101,15 @@ export class NoteDeleteService { } //#endregion - const meta = await this.metaService.fetch(); - this.notesChart.update(note, false); - if (meta.enableChartsForRemoteUser || (user.host == null)) { + if (this.meta.enableChartsForRemoteUser || (user.host == null)) { this.perUserNotesChart.update(user, note, false); } if (this.userEntityService.isRemoteUser(user)) { this.federatedInstanceService.fetch(user.host).then(async i => { this.instancesRepository.decrement({ id: i.id }, 'notesCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateNote(i.host, note, false); } }); diff --git a/packages/backend/src/core/ProxyAccountService.ts b/packages/backend/src/core/ProxyAccountService.ts index 71d663bf90..c3ff2a68d3 100644 --- a/packages/backend/src/core/ProxyAccountService.ts +++ b/packages/backend/src/core/ProxyAccountService.ts @@ -4,26 +4,25 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/_.js'; +import type { MiMeta, UsersRepository } from '@/models/_.js'; import type { MiLocalUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; -import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; @Injectable() export class ProxyAccountService { constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, - - private metaService: MetaService, ) { } @bindThis public async fetch(): Promise { - const meta = await this.metaService.fetch(); - if (meta.proxyAccountId == null) return null; - return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as MiLocalUser; + if (this.meta.proxyAccountId == null) return null; + return await this.usersRepository.findOneByOrFail({ id: this.meta.proxyAccountId }) as MiLocalUser; } } diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index 6a845b951d..1479bb00d9 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -10,8 +10,7 @@ import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { Packed } from '@/misc/json-schema.js'; import { getNoteSummary } from '@/misc/get-note-summary.js'; -import type { MiSwSubscription, SwSubscriptionsRepository } from '@/models/_.js'; -import { MetaService } from '@/core/MetaService.js'; +import type { MiMeta, MiSwSubscription, SwSubscriptionsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { RedisKVCache } from '@/misc/cache.js'; @@ -54,13 +53,14 @@ export class PushNotificationService implements OnApplicationShutdown { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.redis) private redisClient: Redis.Redis, @Inject(DI.swSubscriptionsRepository) private swSubscriptionsRepository: SwSubscriptionsRepository, - - private metaService: MetaService, ) { this.subscriptionsCache = new RedisKVCache(this.redisClient, 'userSwSubscriptions', { lifetime: 1000 * 60 * 60 * 1, // 1h @@ -73,14 +73,12 @@ export class PushNotificationService implements OnApplicationShutdown { @bindThis public async pushNotification(userId: string, type: T, body: PushNotificationsTypes[T]) { - const meta = await this.metaService.fetch(); - - if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return; + if (!this.meta.enableServiceWorker || this.meta.swPublicKey == null || this.meta.swPrivateKey == null) return; // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 push.setVapidDetails(this.config.url, - meta.swPublicKey, - meta.swPrivateKey); + this.meta.swPublicKey, + this.meta.swPrivateKey); const subscriptions = await this.subscriptionsCache.fetch(userId); diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 80827a500b..37028026cc 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -87,6 +87,19 @@ export class QueueService { repeat: { pattern: '*/5 * * * *' }, removeOnComplete: true, }); + + this.systemQueue.add('bakeBufferedReactions', { + }, { + repeat: { pattern: '0 0 * * *' }, + removeOnComplete: true, + }); + + this.systemQueue.add('checkModeratorsActivity', { + }, { + // 毎時30分に起動 + repeat: { pattern: '30 * * * *' }, + removeOnComplete: true, + }); } @bindThis @@ -452,10 +465,15 @@ export class QueueService { /** * @see UserWebhookDeliverJobData - * @see WebhookDeliverProcessorService + * @see UserWebhookDeliverProcessorService */ @bindThis - public userWebhookDeliver(webhook: MiWebhook, type: typeof webhookEventTypes[number], content: unknown) { + public userWebhookDeliver( + webhook: MiWebhook, + type: typeof webhookEventTypes[number], + content: unknown, + opts?: { attempts?: number }, + ) { const data: UserWebhookDeliverJobData = { type, content, @@ -468,7 +486,7 @@ export class QueueService { }; return this.userWebhookDeliverQueue.add(webhook.id, data, { - attempts: 4, + attempts: opts?.attempts ?? 4, backoff: { type: 'custom', }, @@ -479,10 +497,15 @@ export class QueueService { /** * @see SystemWebhookDeliverJobData - * @see WebhookDeliverProcessorService + * @see SystemWebhookDeliverProcessorService */ @bindThis - public systemWebhookDeliver(webhook: MiSystemWebhook, type: SystemWebhookEventType, content: unknown) { + public systemWebhookDeliver( + webhook: MiSystemWebhook, + type: SystemWebhookEventType, + content: unknown, + opts?: { attempts?: number }, + ) { const data: SystemWebhookDeliverJobData = { type, content, @@ -494,7 +517,7 @@ export class QueueService { }; return this.systemWebhookDeliverQueue.add(webhook.id, data, { - attempts: 4, + attempts: opts?.attempts ?? 4, backoff: { type: 'custom', }, diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index 64c7b2ed03..6f9fe53937 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -4,9 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; -import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/_.js'; +import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository, MiMeta } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import type { MiRemoteUser, MiUser } from '@/models/User.js'; import type { MiNote } from '@/models/Note.js'; @@ -21,7 +20,6 @@ import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerServ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; -import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import { UtilityService } from '@/core/UtilityService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; @@ -30,9 +28,10 @@ import { RoleService } from '@/core/RoleService.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { trackPromise } from '@/misc/promise-tracker.js'; import { isQuote, isRenote } from '@/misc/is-renote.js'; +import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; +import { PER_NOTE_REACTION_USER_PAIR_CACHE_MAX } from '@/const.js'; const FALLBACK = '\u2764'; -const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16; const legacies: Record = { 'like': '👍', @@ -71,8 +70,8 @@ const decodeCustomEmojiRegexp = /^:([\w+-]+)(?:@([\w.-]+))?:$/; @Injectable() export class ReactionService { constructor( - @Inject(DI.redis) - private redisClient: Redis.Redis, + @Inject(DI.meta) + private meta: MiMeta, @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -87,12 +86,12 @@ export class ReactionService { private emojisRepository: EmojisRepository, private utilityService: UtilityService, - private metaService: MetaService, private customEmojiService: CustomEmojiService, private roleService: RoleService, private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, private userBlockingService: UserBlockingService, + private reactionsBufferingService: ReactionsBufferingService, private idService: IdService, private featuredService: FeaturedService, private globalEventService: GlobalEventService, @@ -148,6 +147,11 @@ export class ReactionService { if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) { reaction = FALLBACK; } + + // for media silenced host, custom emoji reactions are not allowed + if (reacterHost != null && this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, reacterHost)) { + reaction = FALLBACK; + } } else { // リアクションとして使う権限がない reaction = FALLBACK; @@ -167,7 +171,6 @@ export class ReactionService { reaction, }; - // Create reaction try { await this.noteReactionsRepository.insert(record); } catch (e) { @@ -191,16 +194,20 @@ export class ReactionService { } // Increment reactions count - const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`; - await this.notesRepository.createQueryBuilder().update() - .set({ - reactions: () => sql, - ...(note.reactionAndUserPairCache.length < PER_NOTE_REACTION_USER_PAIR_CACHE_MAX ? { - reactionAndUserPairCache: () => `array_append("reactionAndUserPairCache", '${user.id}/${reaction}')`, - } : {}), - }) - .where('id = :id', { id: note.id }) - .execute(); + if (this.meta.enableReactionsBuffering) { + await this.reactionsBufferingService.create(note.id, user.id, reaction, note.reactionAndUserPairCache); + } else { + const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`; + await this.notesRepository.createQueryBuilder().update() + .set({ + reactions: () => sql, + ...(note.reactionAndUserPairCache.length < PER_NOTE_REACTION_USER_PAIR_CACHE_MAX ? { + reactionAndUserPairCache: () => `array_append("reactionAndUserPairCache", '${user.id}/${reaction}')`, + } : {}), + }) + .where('id = :id', { id: note.id }) + .execute(); + } // 30%の確率、セルフではない、3日以内に投稿されたノートの場合ハイライト用ランキング更新 if ( @@ -220,9 +227,7 @@ export class ReactionService { } } - const meta = await this.metaService.fetch(); - - if (meta.enableChartsForRemoteUser || (user.host == null)) { + if (this.meta.enableChartsForRemoteUser || (user.host == null)) { this.perUserReactionsChart.update(user, note); } @@ -300,14 +305,18 @@ export class ReactionService { } // Decrement reactions count - const sql = `jsonb_set("reactions", '{${exist.reaction}}', (COALESCE("reactions"->>'${exist.reaction}', '0')::int - 1)::text::jsonb)`; - await this.notesRepository.createQueryBuilder().update() - .set({ - reactions: () => sql, - reactionAndUserPairCache: () => `array_remove("reactionAndUserPairCache", '${user.id}/${exist.reaction}')`, - }) - .where('id = :id', { id: note.id }) - .execute(); + if (this.meta.enableReactionsBuffering) { + await this.reactionsBufferingService.delete(note.id, user.id, exist.reaction); + } else { + const sql = `jsonb_set("reactions", '{${exist.reaction}}', (COALESCE("reactions"->>'${exist.reaction}', '0')::int - 1)::text::jsonb)`; + await this.notesRepository.createQueryBuilder().update() + .set({ + reactions: () => sql, + reactionAndUserPairCache: () => `array_remove("reactionAndUserPairCache", '${user.id}/${exist.reaction}')`, + }) + .where('id = :id', { id: note.id }) + .execute(); + } this.globalEventService.publishNoteStream(note.id, 'unreacted', { reaction: this.decodeReaction(exist.reaction).reaction, @@ -329,8 +338,21 @@ export class ReactionService { } /** - * 文字列タイプのレガシーな形式のリアクションを現在の形式に変換しつつ、 - * データベース上には存在する「0個のリアクションがついている」という情報を削除する。 + * - 文字列タイプのレガシーな形式のリアクションを現在の形式に変換する + * - ローカルのリアクションのホストを `@.` にする(`decodeReaction()`の効果) + */ + @bindThis + public convertLegacyReaction(reaction: string): string { + reaction = this.decodeReaction(reaction).reaction; + if (Object.keys(legacies).includes(reaction)) return legacies[reaction]; + return reaction; + } + + // TODO: 廃止 + /** + * - 文字列タイプのレガシーな形式のリアクションを現在の形式に変換する + * - ローカルのリアクションのホストを `@.` にする(`decodeReaction()`の効果) + * - データベース上には存在する「0個のリアクションがついている」という情報を削除する */ @bindThis public convertLegacyReactions(reactions: MiNote['reactions']): MiNote['reactions'] { @@ -343,10 +365,7 @@ export class ReactionService { return count > 0; }) .map(([reaction, count]) => { - // unchecked indexed access - const convertedReaction = legacies[reaction] as string | undefined; - - const key = this.decodeReaction(convertedReaction ?? reaction).reaction; + const key = this.convertLegacyReaction(reaction); return [key, count] as const; }) @@ -401,11 +420,4 @@ export class ReactionService { host: undefined, }; } - - @bindThis - public convertLegacyReaction(reaction: string): string { - reaction = this.decodeReaction(reaction).reaction; - if (Object.keys(legacies).includes(reaction)) return legacies[reaction]; - return reaction; - } } diff --git a/packages/backend/src/core/ReactionsBufferingService.ts b/packages/backend/src/core/ReactionsBufferingService.ts new file mode 100644 index 0000000000..b4207c5106 --- /dev/null +++ b/packages/backend/src/core/ReactionsBufferingService.ts @@ -0,0 +1,211 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as Redis from 'ioredis'; +import { DI } from '@/di-symbols.js'; +import type { MiNote } from '@/models/Note.js'; +import { bindThis } from '@/decorators.js'; +import type { MiUser, NotesRepository } from '@/models/_.js'; +import type { Config } from '@/config.js'; +import { PER_NOTE_REACTION_USER_PAIR_CACHE_MAX } from '@/const.js'; +import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { OnApplicationShutdown } from '@nestjs/common'; + +const REDIS_DELTA_PREFIX = 'reactionsBufferDeltas'; +const REDIS_PAIR_PREFIX = 'reactionsBufferPairs'; + +@Injectable() +export class ReactionsBufferingService implements OnApplicationShutdown { + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, + + @Inject(DI.redisForReactions) + private redisForReactions: Redis.Redis, // TODO: 専用のRedisインスタンスにする + + @Inject(DI.notesRepository) + private notesRepository: NotesRepository, + ) { + this.redisForSub.on('message', this.onMessage); + } + + @bindThis + private async onMessage(_: string, data: string) { + const obj = JSON.parse(data); + + if (obj.channel === 'internal') { + const { type, body } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'metaUpdated': { + // リアクションバッファリングが有効→無効になったら即bake + if (body.before != null && body.before.enableReactionsBuffering && !body.after.enableReactionsBuffering) { + this.bake(); + } + break; + } + default: + break; + } + } + } + + @bindThis + public async create(noteId: MiNote['id'], userId: MiUser['id'], reaction: string, currentPairs: string[]): Promise { + const pipeline = this.redisForReactions.pipeline(); + pipeline.hincrby(`${REDIS_DELTA_PREFIX}:${noteId}`, reaction, 1); + for (let i = 0; i < currentPairs.length; i++) { + pipeline.zadd(`${REDIS_PAIR_PREFIX}:${noteId}`, i, currentPairs[i]); + } + pipeline.zadd(`${REDIS_PAIR_PREFIX}:${noteId}`, Date.now(), `${userId}/${reaction}`); + pipeline.zremrangebyrank(`${REDIS_PAIR_PREFIX}:${noteId}`, 0, -(PER_NOTE_REACTION_USER_PAIR_CACHE_MAX + 1)); + await pipeline.exec(); + } + + @bindThis + public async delete(noteId: MiNote['id'], userId: MiUser['id'], reaction: string): Promise { + const pipeline = this.redisForReactions.pipeline(); + pipeline.hincrby(`${REDIS_DELTA_PREFIX}:${noteId}`, reaction, -1); + pipeline.zrem(`${REDIS_PAIR_PREFIX}:${noteId}`, `${userId}/${reaction}`); + // TODO: 「消した要素一覧」も持っておかないとcreateされた時に上書きされて復活する + await pipeline.exec(); + } + + @bindThis + public async get(noteId: MiNote['id']): Promise<{ + deltas: Record; + pairs: ([MiUser['id'], string])[]; + }> { + const pipeline = this.redisForReactions.pipeline(); + pipeline.hgetall(`${REDIS_DELTA_PREFIX}:${noteId}`); + pipeline.zrange(`${REDIS_PAIR_PREFIX}:${noteId}`, 0, -1); + const results = await pipeline.exec(); + + const resultDeltas = results![0][1] as Record; + const resultPairs = results![1][1] as string[]; + + const deltas = {} as Record; + for (const [name, count] of Object.entries(resultDeltas)) { + deltas[name] = parseInt(count); + } + + const pairs = resultPairs.map(x => x.split('/') as [MiUser['id'], string]); + + return { + deltas, + pairs, + }; + } + + @bindThis + public async getMany(noteIds: MiNote['id'][]): Promise; + pairs: ([MiUser['id'], string])[]; + }>> { + const map = new Map; + pairs: ([MiUser['id'], string])[]; + }>(); + + const pipeline = this.redisForReactions.pipeline(); + for (const noteId of noteIds) { + pipeline.hgetall(`${REDIS_DELTA_PREFIX}:${noteId}`); + pipeline.zrange(`${REDIS_PAIR_PREFIX}:${noteId}`, 0, -1); + } + const results = await pipeline.exec(); + + const opsForEachNotes = 2; + for (let i = 0; i < noteIds.length; i++) { + const noteId = noteIds[i]; + const resultDeltas = results![i * opsForEachNotes][1] as Record; + const resultPairs = results![i * opsForEachNotes + 1][1] as string[]; + + const deltas = {} as Record; + for (const [name, count] of Object.entries(resultDeltas)) { + deltas[name] = parseInt(count); + } + + const pairs = resultPairs.map(x => x.split('/') as [MiUser['id'], string]); + + map.set(noteId, { + deltas, + pairs, + }); + } + + return map; + } + + // TODO: scanは重い可能性があるので、別途 bufferedNoteIds を直接Redis上に持っておいてもいいかもしれない + @bindThis + public async bake(): Promise { + const bufferedNoteIds = []; + let cursor = '0'; + do { + // https://github.com/redis/ioredis#transparent-key-prefixing + const result = await this.redisForReactions.scan( + cursor, + 'MATCH', + `${this.config.redis.prefix}:${REDIS_DELTA_PREFIX}:*`, + 'COUNT', + '1000'); + + cursor = result[0]; + bufferedNoteIds.push(...result[1].map(x => x.replace(`${this.config.redis.prefix}:${REDIS_DELTA_PREFIX}:`, ''))); + } while (cursor !== '0'); + + const bufferedMap = await this.getMany(bufferedNoteIds); + + // clear + const pipeline = this.redisForReactions.pipeline(); + for (const noteId of bufferedNoteIds) { + pipeline.del(`${REDIS_DELTA_PREFIX}:${noteId}`); + pipeline.del(`${REDIS_PAIR_PREFIX}:${noteId}`); + } + await pipeline.exec(); + + // TODO: SQL一個にまとめたい + for (const [noteId, buffered] of bufferedMap) { + const sql = Object.entries(buffered.deltas) + .map(([reaction, count]) => + `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + ${count})::text::jsonb)`) + .join(' || '); + + this.notesRepository.createQueryBuilder().update() + .set({ + reactions: () => sql, + reactionAndUserPairCache: buffered.pairs.map(x => x.join('/')), + }) + .where('id = :id', { id: noteId }) + .execute(); + } + } + + @bindThis + public mergeReactions(src: MiNote['reactions'], delta: Record): MiNote['reactions'] { + const reactions = { ...src }; + for (const [name, count] of Object.entries(delta)) { + if (reactions[name] != null) { + reactions[name] += count; + } else { + reactions[name] = count; + } + } + return reactions; + } + + @bindThis + public dispose(): void { + this.redisForSub.off('message', this.onMessage); + } + + @bindThis + public onApplicationShutdown(signal?: string | undefined): void { + this.dispose(); + } +} diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index 8dd3d64f5b..db32114346 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -35,7 +35,7 @@ export class RelayService { private createSystemUserService: CreateSystemUserService, private apRendererService: ApRendererService, ) { - this.relaysCache = new MemorySingleCache(1000 * 60 * 10); + this.relaysCache = new MemorySingleCache(1000 * 60 * 10); // 10m } @bindThis diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index 7f939b99c7..51dca3da59 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -6,6 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { ModuleRef } from '@nestjs/core'; +import { reversiUpdateKeys } from 'misskey-js'; import * as Reversi from 'misskey-reversi'; import { IsNull, LessThan, MoreThan } from 'typeorm'; import type { @@ -399,7 +400,33 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { } @bindThis - public async updateSettings(gameId: MiReversiGame['id'], user: MiUser, key: string, value: any) { + public isValidReversiUpdateKey(key: unknown): key is typeof reversiUpdateKeys[number] { + if (typeof key !== 'string') return false; + return (reversiUpdateKeys as string[]).includes(key); + } + + @bindThis + public isValidReversiUpdateValue(key: K, value: unknown): value is MiReversiGame[K] { + switch (key) { + case 'map': + return Array.isArray(value) && value.every(row => typeof row === 'string'); + case 'bw': + return typeof value === 'string' && ['random', '1', '2'].includes(value); + case 'isLlotheo': + return typeof value === 'boolean'; + case 'canPutEverywhere': + return typeof value === 'boolean'; + case 'loopedBoard': + return typeof value === 'boolean'; + case 'timeLimitForEachTurn': + return typeof value === 'number' && value >= 0; + default: + return false; + } + } + + @bindThis + public async updateSettings(gameId: MiReversiGame['id'], user: MiUser, key: K, value: MiReversiGame[K]) { const game = await this.get(gameId); if (game == null) throw new Error('game not found'); if (game.isStarted) return; @@ -407,10 +434,6 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { if ((game.user1Id === user.id) && game.user1Ready) return; if ((game.user2Id === user.id) && game.user2Ready) return; - if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard', 'timeLimitForEachTurn'].includes(key)) return; - - // TODO: より厳格なバリデーション - const updatedGame = { ...game, [key]: value, diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index e2ebecb99f..5af6b05942 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -8,6 +8,7 @@ import * as Redis from 'ioredis'; import { In } from 'typeorm'; import { ModuleRef } from '@nestjs/core'; import type { + MiMeta, MiRole, MiRoleAssignment, RoleAssignmentsRepository, @@ -18,7 +19,6 @@ import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js'; import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; import { CacheService } from '@/core/CacheService.js'; import type { RoleCondFormulaValue } from '@/models/Role.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -47,6 +47,7 @@ export type RolePolicies = { canHideAds: boolean; driveCapacityMb: number; alwaysMarkNsfw: boolean; + canUpdateBioMedia: boolean; pinLimit: number; antennaLimit: number; wordMuteLimit: number; @@ -57,6 +58,11 @@ export type RolePolicies = { userEachUserListsLimit: number; rateLimitFactor: number; avatarDecorationLimit: number; + canImportAntennas: boolean; + canImportBlocking: boolean; + canImportFollowing: boolean; + canImportMuting: boolean; + canImportUserLists: boolean; }; export const DEFAULT_POLICIES: RolePolicies = { @@ -75,6 +81,7 @@ export const DEFAULT_POLICIES: RolePolicies = { canHideAds: false, driveCapacityMb: 100, alwaysMarkNsfw: false, + canUpdateBioMedia: true, pinLimit: 5, antennaLimit: 5, wordMuteLimit: 200, @@ -85,10 +92,16 @@ export const DEFAULT_POLICIES: RolePolicies = { userEachUserListsLimit: 50, rateLimitFactor: 1, avatarDecorationLimit: 1, + canImportAntennas: true, + canImportBlocking: true, + canImportFollowing: true, + canImportMuting: true, + canImportUserLists: true, }; @Injectable() export class RoleService implements OnApplicationShutdown, OnModuleInit { + private rootUserIdCache: MemorySingleCache; private rolesCache: MemorySingleCache; private roleAssignmentByUserIdCache: MemoryKVCache; private notificationService: NotificationService; @@ -99,8 +112,8 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { constructor( private moduleRef: ModuleRef, - @Inject(DI.redis) - private redisClient: Redis.Redis, + @Inject(DI.meta) + private meta: MiMeta, @Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis, @@ -117,7 +130,6 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { @Inject(DI.roleAssignmentsRepository) private roleAssignmentsRepository: RoleAssignmentsRepository, - private metaService: MetaService, private cacheService: CacheService, private userEntityService: UserEntityService, private globalEventService: GlobalEventService, @@ -125,10 +137,9 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { private moderationLogService: ModerationLogService, private fanoutTimelineService: FanoutTimelineService, ) { - //this.onMessage = this.onMessage.bind(this); - - this.rolesCache = new MemorySingleCache(1000 * 60 * 60 * 1); - this.roleAssignmentByUserIdCache = new MemoryKVCache(1000 * 60 * 60 * 1); + this.rootUserIdCache = new MemorySingleCache(1000 * 60 * 60 * 24 * 7); // 1week. rootユーザのIDは不変なので長めに + this.rolesCache = new MemorySingleCache(1000 * 60 * 60); // 1h + this.roleAssignmentByUserIdCache = new MemoryKVCache(1000 * 60 * 5); // 5m this.redisForSub.on('message', this.onMessage); } @@ -339,8 +350,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { @bindThis public async getUserPolicies(userId: MiUser['id'] | null): Promise { - const meta = await this.metaService.fetch(); - const basePolicies = { ...DEFAULT_POLICIES, ...meta.policies }; + const basePolicies = { ...DEFAULT_POLICIES, ...this.meta.policies }; if (userId == null) return basePolicies; @@ -376,6 +386,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { canHideAds: calc('canHideAds', vs => vs.some(v => v === true)), driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)), alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)), + canUpdateBioMedia: calc('canUpdateBioMedia', vs => vs.some(v => v === true)), pinLimit: calc('pinLimit', vs => Math.max(...vs)), antennaLimit: calc('antennaLimit', vs => Math.max(...vs)), wordMuteLimit: calc('wordMuteLimit', vs => Math.max(...vs)), @@ -386,6 +397,11 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { userEachUserListsLimit: calc('userEachUserListsLimit', vs => Math.max(...vs)), rateLimitFactor: calc('rateLimitFactor', vs => Math.max(...vs)), avatarDecorationLimit: calc('avatarDecorationLimit', vs => Math.max(...vs)), + canImportAntennas: calc('canImportAntennas', vs => vs.some(v => v === true)), + canImportBlocking: calc('canImportBlocking', vs => vs.some(v => v === true)), + canImportFollowing: calc('canImportFollowing', vs => vs.some(v => v === true)), + canImportMuting: calc('canImportMuting', vs => vs.some(v => v === true)), + canImportUserLists: calc('canImportUserLists', vs => vs.some(v => v === true)), }; } @@ -402,49 +418,78 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { } @bindThis - public async isExplorable(role: { id: MiRole['id']} | null): Promise { + public async isExplorable(role: { id: MiRole['id'] } | null): Promise { if (role == null) return false; const check = await this.rolesRepository.findOneBy({ id: role.id }); if (check == null) return false; return check.isExplorable; } + /** + * モデレーター権限のロールが割り当てられているユーザID一覧を取得する. + * + * @param opts.includeAdmins 管理者権限も含めるか(デフォルト: true) + * @param opts.includeRoot rootユーザも含めるか(デフォルト: false) + * @param opts.excludeExpire 期限切れのロールを除外するか(デフォルト: false) + */ @bindThis - public async getModeratorIds(includeAdmins = true, excludeExpire = false): Promise { + public async getModeratorIds(opts?: { + includeAdmins?: boolean, + includeRoot?: boolean, + excludeExpire?: boolean, + }): Promise { + const includeAdmins = opts?.includeAdmins ?? true; + const includeRoot = opts?.includeRoot ?? false; + const excludeExpire = opts?.excludeExpire ?? false; + const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({})); const moderatorRoles = includeAdmins ? roles.filter(r => r.isModerator || r.isAdministrator) : roles.filter(r => r.isModerator); - // TODO: isRootなアカウントも含める const assigns = moderatorRoles.length > 0 ? await this.roleAssignmentsRepository.findBy({ roleId: In(moderatorRoles.map(r => r.id)) }) : []; + // Setを経由して重複を除去(ユーザIDは重複する可能性があるので) const now = Date.now(); - const result = [ - // Setを経由して重複を除去(ユーザIDは重複する可能性があるので) - ...new Set( - assigns - .filter(it => - (excludeExpire) - ? (it.expiresAt == null || it.expiresAt.getTime() > now) - : true, - ) - .map(a => a.userId), - ), - ]; + const resultSet = new Set( + assigns + .filter(it => + (excludeExpire) + ? (it.expiresAt == null || it.expiresAt.getTime() > now) + : true, + ) + .map(a => a.userId), + ); - return result.sort((x, y) => x.localeCompare(y)); + if (includeRoot) { + const rootUserId = await this.rootUserIdCache.fetch(async () => { + const it = await this.usersRepository.createQueryBuilder('users') + .select('id') + .where({ isRoot: true }) + .getRawOne<{ id: string }>(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return it!.id; + }); + resultSet.add(rootUserId); + } + + return [...resultSet].sort((x, y) => x.localeCompare(y)); } @bindThis - public async getModerators(includeAdmins = true): Promise { - const ids = await this.getModeratorIds(includeAdmins); - const users = ids.length > 0 ? await this.usersRepository.findBy({ - id: In(ids), - }) : []; - return users; + public async getModerators(opts?: { + includeAdmins?: boolean, + includeRoot?: boolean, + excludeExpire?: boolean, + }): Promise { + const ids = await this.getModeratorIds(opts); + return ids.length > 0 + ? await this.usersRepository.findBy({ + id: In(ids), + }) + : []; } @bindThis @@ -502,14 +547,15 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { this.globalEventService.publishInternalEvent('userRoleAssigned', created); - if (role.isPublic) { + const user = await this.usersRepository.findOneByOrFail({ id: userId }); + + if (role.isPublic && user.host === null) { this.notificationService.createNotification(userId, 'roleAssigned', { roleId: roleId, }); } if (moderator) { - const user = await this.usersRepository.findOneByOrFail({ id: userId }); this.moderationLogService.log(moderator, 'assignRole', { roleId: roleId, roleName: role.name, diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts index 5522ecd6cc..cc8a3d6461 100644 --- a/packages/backend/src/core/SignupService.ts +++ b/packages/backend/src/core/SignupService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { DataSource, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; +import type { MiMeta, UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; import { MiUser } from '@/models/User.js'; import { MiUserProfile } from '@/models/UserProfile.js'; import { IdService } from '@/core/IdService.js'; @@ -20,7 +20,7 @@ import { InstanceActorService } from '@/core/InstanceActorService.js'; import { bindThis } from '@/decorators.js'; import UsersChart from '@/core/chart/charts/users.js'; import { UtilityService } from '@/core/UtilityService.js'; -import { MetaService } from '@/core/MetaService.js'; +import { UserService } from '@/core/UserService.js'; @Injectable() export class SignupService { @@ -28,6 +28,9 @@ export class SignupService { @Inject(DI.db) private db: DataSource, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -35,9 +38,9 @@ export class SignupService { private usedUsernamesRepository: UsedUsernamesRepository, private utilityService: UtilityService, + private userService: UserService, private userEntityService: UserEntityService, private idService: IdService, - private metaService: MetaService, private instanceActorService: InstanceActorService, private usersChart: UsersChart, ) { @@ -86,8 +89,7 @@ export class SignupService { const isTheFirstUser = !await this.instanceActorService.realLocalUsersPresent(); if (!opts.ignorePreservedUsernames && !isTheFirstUser) { - const instance = await this.metaService.fetch(true); - const isPreserved = instance.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase()); + const isPreserved = this.meta.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase()); if (isPreserved) { throw new Error('USED_USERNAME'); } @@ -148,7 +150,8 @@ export class SignupService { })); }); - this.usersChart.update(account, true); + this.usersChart.update(account, true).then(); + this.userService.notifySystemWebhook(account, 'userCreated').then(); return { account, secret }; } diff --git a/packages/backend/src/core/SystemWebhookService.ts b/packages/backend/src/core/SystemWebhookService.ts index bc6851f788..bb7c6b8c0e 100644 --- a/packages/backend/src/core/SystemWebhookService.ts +++ b/packages/backend/src/core/SystemWebhookService.ts @@ -54,7 +54,7 @@ export class SystemWebhookService implements OnApplicationShutdown { * SystemWebhook の一覧を取得する. */ @bindThis - public async fetchSystemWebhooks(params?: { + public fetchSystemWebhooks(params?: { ids?: MiSystemWebhook['id'][]; isActive?: MiSystemWebhook['isActive']; on?: MiSystemWebhook['on']; @@ -165,19 +165,24 @@ export class SystemWebhookService implements OnApplicationShutdown { /** * SystemWebhook をWebhook配送キューに追加する * @see QueueService.systemWebhookDeliver + * // TODO: contentの型を厳格化する */ @bindThis - public async enqueueSystemWebhook(webhook: MiSystemWebhook | MiSystemWebhook['id'], type: SystemWebhookEventType, content: unknown) { + public async enqueueSystemWebhook( + webhook: MiSystemWebhook | MiSystemWebhook['id'], + type: T, + content: unknown, + ) { const webhookEntity = typeof webhook === 'string' ? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook) : webhook; if (!webhookEntity || !webhookEntity.isActive) { - this.logger.info(`Webhook is not active or not found : ${webhook}`); + this.logger.info(`SystemWebhook is not active or not found : ${webhook}`); return; } if (!webhookEntity.on.includes(type)) { - this.logger.info(`Webhook ${webhookEntity.id} is not listening to ${type}`); + this.logger.info(`SystemWebhook ${webhookEntity.id} is not listening to ${type}`); return; } diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 267a6a3f1b..77e7b60bea 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -13,23 +13,20 @@ import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { IdService } from '@/core/IdService.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; -import type { Packed } from '@/misc/json-schema.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { UserWebhookService } from '@/core/UserWebhookService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, MiMeta, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { bindThis } from '@/decorators.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; -import { MetaService } from '@/core/MetaService.js'; import { CacheService } from '@/core/CacheService.js'; import type { Config } from '@/config.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; import { UtilityService } from '@/core/UtilityService.js'; -import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import type { ThinUser } from '@/queue/types.js'; import Logger from '../logger.js'; @@ -58,6 +55,9 @@ export class UserFollowingService implements OnModuleInit { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -79,13 +79,11 @@ export class UserFollowingService implements OnModuleInit { private idService: IdService, private queueService: QueueService, private globalEventService: GlobalEventService, - private metaService: MetaService, private notificationService: NotificationService, private federatedInstanceService: FederatedInstanceService, private webhookService: UserWebhookService, private apRendererService: ApRendererService, private accountMoveService: AccountMoveService, - private fanoutTimelineService: FanoutTimelineService, private perUserFollowingChart: PerUserFollowingChart, private instanceChart: InstanceChart, ) { @@ -172,7 +170,7 @@ export class UserFollowingService implements OnModuleInit { followee.isLocked || (followeeProfile.carefulBot && follower.isBot) || (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee) && process.env.FORCE_FOLLOW_REMOTE_USER_FOR_TESTING !== 'true') || - (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower) && this.utilityService.isSilencedHost((await this.metaService.fetch()).silencedHosts, follower.host)) + (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower) && this.utilityService.isSilencedHost(this.meta.silencedHosts, follower.host)) ) { let autoAccept = false; @@ -277,14 +275,19 @@ export class UserFollowingService implements OnModuleInit { followeeId: followee.id, followerId: follower.id, }); - - // 通知を作成 - this.notificationService.createNotification(follower.id, 'followRequestAccepted', { - }, followee.id); } if (alreadyFollowed) return; + // 通知を作成 + if (follower.host === null) { + const profile = await this.cacheService.userProfileCache.fetch(followee.id); + + this.notificationService.createNotification(follower.id, 'followRequestAccepted', { + message: profile.followedMessage, + }, followee.id); + } + this.globalEventService.publishInternalEvent('follow', { followerId: follower.id, followeeId: followee.id }); const [followeeUser, followerUser] = await Promise.all([ @@ -305,14 +308,14 @@ export class UserFollowingService implements OnModuleInit { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { this.federatedInstanceService.fetch(follower.host).then(async i => { this.instancesRepository.increment({ id: i.id }, 'followingCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateFollowing(i.host, true); } }); } else if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { this.federatedInstanceService.fetch(followee.host).then(async i => { this.instancesRepository.increment({ id: i.id }, 'followersCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateFollowers(i.host, true); } }); @@ -437,14 +440,14 @@ export class UserFollowingService implements OnModuleInit { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { this.federatedInstanceService.fetch(follower.host).then(async i => { this.instancesRepository.decrement({ id: i.id }, 'followingCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateFollowing(i.host, false); } }); } else if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { this.federatedInstanceService.fetch(followee.host).then(async i => { this.instancesRepository.decrement({ id: i.id }, 'followersCount', 1); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.updateFollowers(i.host, false); } }); diff --git a/packages/backend/src/core/UserKeypairService.ts b/packages/backend/src/core/UserKeypairService.ts index 51ac99179a..92d61cd103 100644 --- a/packages/backend/src/core/UserKeypairService.ts +++ b/packages/backend/src/core/UserKeypairService.ts @@ -25,7 +25,7 @@ export class UserKeypairService implements OnApplicationShutdown { ) { this.cache = new RedisKVCache(this.redisClient, 'userKeypair', { lifetime: 1000 * 60 * 60 * 24, // 24h - memoryCacheLifetime: Infinity, + memoryCacheLifetime: 1000 * 60 * 60, // 1h fetcher: (key) => this.userKeypairsRepository.findOneByOrFail({ userId: key }), toRedisConverter: (value) => JSON.stringify(value), fromRedisConverter: (value) => JSON.parse(value), diff --git a/packages/backend/src/core/UserRenoteMutingService.ts b/packages/backend/src/core/UserRenoteMutingService.ts new file mode 100644 index 0000000000..bdc5e23f4b --- /dev/null +++ b/packages/backend/src/core/UserRenoteMutingService.ts @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project , Type4ny-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; +import type { RenoteMutingsRepository } from '@/models/_.js'; +import type { MiRenoteMuting } from '@/models/RenoteMuting.js'; + +import { IdService } from '@/core/IdService.js'; +import type { MiUser } from '@/models/User.js'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import { CacheService } from '@/core/CacheService.js'; + +@Injectable() +export class UserRenoteMutingService { + constructor( + @Inject(DI.renoteMutingsRepository) + private renoteMutingsRepository: RenoteMutingsRepository, + + private idService: IdService, + private cacheService: CacheService, + ) { + } + + @bindThis + public async mute(user: MiUser, target: MiUser, expiresAt: Date | null = null): Promise { + await this.renoteMutingsRepository.insert({ + id: this.idService.gen(), + muterId: user.id, + muteeId: target.id, + }); + + await this.cacheService.renoteMutingsCache.refresh(user.id); + } + + @bindThis + public async unmute(mutings: MiRenoteMuting[]): Promise { + if (mutings.length === 0) return; + + await this.renoteMutingsRepository.delete({ + id: In(mutings.map(m => m.id)), + }); + + const muterIds = [...new Set(mutings.map(m => m.muterId))]; + for (const muterId of muterIds) { + await this.cacheService.renoteMutingsCache.refresh(muterId); + } + } +} diff --git a/packages/backend/src/core/UserSearchService.ts b/packages/backend/src/core/UserSearchService.ts new file mode 100644 index 0000000000..0d03cf6ee0 --- /dev/null +++ b/packages/backend/src/core/UserSearchService.ts @@ -0,0 +1,205 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Brackets, SelectQueryBuilder } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import { type FollowingsRepository, MiUser, type UsersRepository } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; +import type { Config } from '@/config.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { Packed } from '@/misc/json-schema.js'; + +function defaultActiveThreshold() { + return new Date(Date.now() - 1000 * 60 * 60 * 24 * 30); +} + +@Injectable() +export class UserSearchService { + constructor( + @Inject(DI.config) + private config: Config, + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + @Inject(DI.followingsRepository) + private followingsRepository: FollowingsRepository, + private userEntityService: UserEntityService, + ) { + } + + /** + * ユーザ名とホスト名によるユーザ検索を行う. + * + * - 検索結果には優先順位がつけられており、以下の順序で検索が行われる. + * 1. フォローしているユーザのうち、一定期間以内(※)に更新されたユーザ + * 2. フォローしているユーザのうち、一定期間以内に更新されていないユーザ + * 3. フォローしていないユーザのうち、一定期間以内に更新されたユーザ + * 4. フォローしていないユーザのうち、一定期間以内に更新されていないユーザ + * - ログインしていない場合は、以下の順序で検索が行われる. + * 1. 一定期間以内に更新されたユーザ + * 2. 一定期間以内に更新されていないユーザ + * - それぞれの検索結果はユーザ名の昇順でソートされる. + * - 動作的には先に登場した検索結果の登場位置が優先される(条件的にユーザIDが重複することはないが). + * (1で既にヒットしていた場合、2, 3, 4でヒットしても無視される) + * - ユーザ名とホスト名の検索条件はそれぞれ前方一致で検索される. + * - ユーザ名の検索は大文字小文字を区別しない. + * - ホスト名の検索は大文字小文字を区別しない. + * - 検索結果は最大で {@link opts.limit} 件までとなる. + * + * ※一定期間とは {@link params.activeThreshold} で指定された日時から現在までの期間を指す. + * + * @param params 検索条件. + * @param opts 関数の動作を制御するオプション. + * @param me 検索を実行するユーザの情報. 未ログインの場合は指定しない. + * @see {@link UserSearchService#buildSearchUserQueries} + * @see {@link UserSearchService#buildSearchUserNoLoginQueries} + */ + @bindThis + public async search( + params: { + username?: string | null, + host?: string | null, + activeThreshold?: Date, + }, + opts?: { + limit?: number, + detail?: boolean, + }, + me?: MiUser | null, + ): Promise[]> { + const queries = me ? this.buildSearchUserQueries(me, params) : this.buildSearchUserNoLoginQueries(params); + + let resultSet = new Set(); + const limit = opts?.limit ?? 10; + for (const query of queries) { + const ids = await query + .select('user.id') + .limit(limit - resultSet.size) + .orderBy('user.usernameLower', 'ASC') + .getRawMany<{ user_id: MiUser['id'] }>() + .then(res => res.map(x => x.user_id)); + + resultSet = new Set([...resultSet, ...ids]); + if (resultSet.size >= limit) { + break; + } + } + + return this.userEntityService.packMany<'UserLite' | 'UserDetailed'>( + [...resultSet].slice(0, limit), + me, + { schema: opts?.detail ? 'UserDetailed' : 'UserLite' }, + ); + } + + /** + * ログイン済みユーザによる検索実行時のクエリ一覧を構築する. + * @param me + * @param params + * @private + */ + @bindThis + private buildSearchUserQueries( + me: MiUser, + params: { + username?: string | null, + host?: string | null, + activeThreshold?: Date, + }, + ) { + // デフォルト30日以内に更新されたユーザーをアクティブユーザーとする + const activeThreshold = params.activeThreshold ?? defaultActiveThreshold(); + + const followingUserQuery = this.followingsRepository.createQueryBuilder('following') + .select('following.followeeId') + .where('following.followerId = :followerId', { followerId: me.id }); + + const activeFollowingUsersQuery = this.generateUserQueryBuilder(params) + .andWhere(`user.id IN (${followingUserQuery.getQuery()})`) + .andWhere('user.updatedAt > :activeThreshold', { activeThreshold }); + activeFollowingUsersQuery.setParameters(followingUserQuery.getParameters()); + + const inactiveFollowingUsersQuery = this.generateUserQueryBuilder(params) + .andWhere(`user.id IN (${followingUserQuery.getQuery()})`) + .andWhere(new Brackets(qb => { + qb + .where('user.updatedAt IS NULL') + .orWhere('user.updatedAt <= :activeThreshold', { activeThreshold }); + })); + inactiveFollowingUsersQuery.setParameters(followingUserQuery.getParameters()); + + // 自分自身がヒットするとしたらここ + const activeUserQuery = this.generateUserQueryBuilder(params) + .andWhere(`user.id NOT IN (${followingUserQuery.getQuery()})`) + .andWhere('user.updatedAt > :activeThreshold', { activeThreshold }); + activeUserQuery.setParameters(followingUserQuery.getParameters()); + + const inactiveUserQuery = this.generateUserQueryBuilder(params) + .andWhere(`user.id NOT IN (${followingUserQuery.getQuery()})`) + .andWhere('user.updatedAt <= :activeThreshold', { activeThreshold }); + inactiveUserQuery.setParameters(followingUserQuery.getParameters()); + + return [activeFollowingUsersQuery, inactiveFollowingUsersQuery, activeUserQuery, inactiveUserQuery]; + } + + /** + * ログインしていないユーザによる検索実行時のクエリ一覧を構築する. + * @param params + * @private + */ + @bindThis + private buildSearchUserNoLoginQueries(params: { + username?: string | null, + host?: string | null, + activeThreshold?: Date, + }) { + // デフォルト30日以内に更新されたユーザーをアクティブユーザーとする + const activeThreshold = params.activeThreshold ?? defaultActiveThreshold(); + + const activeUserQuery = this.generateUserQueryBuilder(params) + .andWhere(new Brackets(qb => { + qb + .where('user.updatedAt IS NULL') + .orWhere('user.updatedAt > :activeThreshold', { activeThreshold }); + })); + + const inactiveUserQuery = this.generateUserQueryBuilder(params) + .andWhere('user.updatedAt <= :activeThreshold', { activeThreshold }); + + return [activeUserQuery, inactiveUserQuery]; + } + + /** + * ユーザ検索クエリで共通する抽出条件をあらかじめ設定したクエリビルダを生成する. + * @param params + * @private + */ + @bindThis + private generateUserQueryBuilder(params: { + username?: string | null, + host?: string | null, + }): SelectQueryBuilder { + const userQuery = this.usersRepository.createQueryBuilder('user'); + + if (params.username) { + userQuery.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(params.username.toLowerCase()) + '%' }); + } + + if (params.host) { + if (params.host === this.config.hostname || params.host === '.') { + userQuery.andWhere('user.host IS NULL'); + } else { + userQuery.andWhere('user.host LIKE :host', { + host: sqlLikeEscape(params.host.toLowerCase()) + '%', + }); + } + } + + userQuery.andWhere('user.isSuspended = FALSE'); + + return userQuery; + } +} diff --git a/packages/backend/src/core/UserService.ts b/packages/backend/src/core/UserService.ts index 72fa4d928d..9b1961c631 100644 --- a/packages/backend/src/core/UserService.ts +++ b/packages/backend/src/core/UserService.ts @@ -8,15 +8,18 @@ import type { FollowingsRepository, UsersRepository } from '@/models/_.js'; import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; @Injectable() export class UserService { constructor( @Inject(DI.usersRepository) private usersRepository: UsersRepository, - @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, + private systemWebhookService: SystemWebhookService, + private userEntityService: UserEntityService, ) { } @@ -50,4 +53,23 @@ export class UserService { }); } } + + /** + * SystemWebhookを用いてユーザに関する操作内容を管理者各位に通知する. + * ここではJobQueueへのエンキューのみを行うため、即時実行されない. + * + * @see SystemWebhookService.enqueueSystemWebhook + */ + @bindThis + public async notifySystemWebhook(user: MiUser, type: 'userCreated') { + const packedUser = await this.userEntityService.pack(user, null, { schema: 'UserLite' }); + const recipientWebhookIds = await this.systemWebhookService.fetchSystemWebhooks({ isActive: true, on: [type] }); + for (const webhookId of recipientWebhookIds) { + await this.systemWebhookService.enqueueSystemWebhook( + webhookId, + type, + packedUser, + ); + } + } } diff --git a/packages/backend/src/core/UserSuspendService.ts b/packages/backend/src/core/UserSuspendService.ts index d594a223f4..7920e58e36 100644 --- a/packages/backend/src/core/UserSuspendService.ts +++ b/packages/backend/src/core/UserSuspendService.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Not, IsNull } from 'typeorm'; -import type { FollowingsRepository } from '@/models/_.js'; +import type { FollowingsRepository, FollowRequestsRepository, UsersRepository } from '@/models/_.js'; import type { MiUser } from '@/models/User.js'; import { QueueService } from '@/core/QueueService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; @@ -13,24 +13,75 @@ import { DI } from '@/di-symbols.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; +import { RelationshipJobData } from '@/queue/types.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; @Injectable() export class UserSuspendService { constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, + @Inject(DI.followRequestsRepository) + private followRequestsRepository: FollowRequestsRepository, + private userEntityService: UserEntityService, private queueService: QueueService, private globalEventService: GlobalEventService, private apRendererService: ApRendererService, + private moderationLogService: ModerationLogService, ) { } @bindThis - public async doPostSuspend(user: { id: MiUser['id']; host: MiUser['host'] }): Promise { + public async suspend(user: MiUser, moderator: MiUser): Promise { + await this.usersRepository.update(user.id, { + isSuspended: true, + }); + + this.moderationLogService.log(moderator, 'suspend', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + }); + + (async () => { + await this.postSuspend(user).catch(e => {}); + await this.unFollowAll(user).catch(e => {}); + })(); + } + + @bindThis + public async unsuspend(user: MiUser, moderator: MiUser): Promise { + await this.usersRepository.update(user.id, { + isSuspended: false, + }); + + this.moderationLogService.log(moderator, 'unsuspend', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + }); + + (async () => { + await this.postUnsuspend(user).catch(e => {}); + })(); + } + + @bindThis + private async postSuspend(user: { id: MiUser['id']; host: MiUser['host'] }): Promise { this.globalEventService.publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: true }); + this.followRequestsRepository.delete({ + followeeId: user.id, + }); + this.followRequestsRepository.delete({ + followerId: user.id, + }); + if (this.userEntityService.isLocalUser(user)) { // 知り得る全SharedInboxにDelete配信 const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.userEntityService.genLocalUserUri(user.id), user)); @@ -58,7 +109,7 @@ export class UserSuspendService { } @bindThis - public async doPostUnsuspend(user: MiUser): Promise { + private async postUnsuspend(user: MiUser): Promise { this.globalEventService.publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: false }); if (this.userEntityService.isLocalUser(user)) { @@ -86,4 +137,26 @@ export class UserSuspendService { } } } + + @bindThis + private async unFollowAll(follower: MiUser) { + const followings = await this.followingsRepository.find({ + where: { + followerId: follower.id, + followeeId: Not(IsNull()), + }, + }); + + const jobs: RelationshipJobData[] = []; + for (const following of followings) { + if (following.followeeId && following.followerId) { + jobs.push({ + from: { id: following.followerId }, + to: { id: following.followeeId }, + silent: true, + }); + } + } + this.queueService.createUnfollowJob(jobs); + } } diff --git a/packages/backend/src/core/UserWebhookService.ts b/packages/backend/src/core/UserWebhookService.ts index e96bfeea95..8a40a53688 100644 --- a/packages/backend/src/core/UserWebhookService.ts +++ b/packages/backend/src/core/UserWebhookService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { WebhooksRepository } from '@/models/_.js'; -import type { MiWebhook } from '@/models/Webhook.js'; +import { type WebhooksRepository } from '@/models/_.js'; +import { MiWebhook } from '@/models/Webhook.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { GlobalEvents } from '@/core/GlobalEventService.js'; @@ -38,6 +38,31 @@ export class UserWebhookService implements OnApplicationShutdown { return this.activeWebhooks; } + /** + * UserWebhook の一覧を取得する. + */ + @bindThis + public fetchWebhooks(params?: { + ids?: MiWebhook['id'][]; + isActive?: MiWebhook['active']; + on?: MiWebhook['on']; + }): Promise { + const query = this.webhooksRepository.createQueryBuilder('webhook'); + if (params) { + if (params.ids && params.ids.length > 0) { + query.andWhere('webhook.id IN (:...ids)', { ids: params.ids }); + } + if (params.isActive !== undefined) { + query.andWhere('webhook.active = :isActive', { isActive: params.isActive }); + } + if (params.on && params.on.length > 0) { + query.andWhere(':on <@ webhook.on', { on: params.on }); + } + } + + return query.getMany(); + } + @bindThis private async onMessage(_: string, data: string): Promise { const obj = JSON.parse(data); diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts index 652e8f7449..86082ccdcd 100644 --- a/packages/backend/src/core/UtilityService.ts +++ b/packages/backend/src/core/UtilityService.ts @@ -10,12 +10,16 @@ import RE2 from 're2'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; +import { MiMeta } from '@/models/Meta.js'; @Injectable() export class UtilityService { constructor( @Inject(DI.config) private config: Config, + + @Inject(DI.meta) + private meta: MiMeta, ) { } @@ -42,6 +46,12 @@ export class UtilityService { return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`)); } + @bindThis + public isMediaSilencedHost(silencedHosts: string[] | undefined, host: string | null): boolean { + if (!silencedHosts || host == null) return false; + return silencedHosts.some(x => host.toLowerCase() === x); + } + @bindThis public concatNoteContentsForKeyWordCheck(content: { cw?: string | null; @@ -99,4 +109,19 @@ export class UtilityService { if (host == null) return null; return toASCII(host.toLowerCase()); } + + @bindThis + public isFederationAllowedHost(host: string): boolean { + if (this.meta.federation === 'none') return false; + if (this.meta.federation === 'specified' && !this.meta.federationHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`))) return false; + if (this.isBlockedHost(this.meta.blockedHosts, host)) return false; + + return true; + } + + @bindThis + public isFederationAllowedUri(uri: string): boolean { + const host = this.extractDbHost(uri); + return this.isFederationAllowedHost(host); + } } diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts index ec9f4484a4..75ab0a207c 100644 --- a/packages/backend/src/core/WebAuthnService.ts +++ b/packages/backend/src/core/WebAuthnService.ts @@ -12,10 +12,9 @@ import { } from '@simplewebauthn/server'; import { AttestationFormat, isoCBOR, isoUint8Array } from '@simplewebauthn/server/helpers'; import { DI } from '@/di-symbols.js'; -import type { UserSecurityKeysRepository } from '@/models/_.js'; +import type { MiMeta, UserSecurityKeysRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; import { MiUser } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import type { @@ -23,7 +22,6 @@ import type { AuthenticatorTransportFuture, CredentialDeviceType, PublicKeyCredentialCreationOptionsJSON, - PublicKeyCredentialDescriptorFuture, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON, } from '@simplewebauthn/types'; @@ -31,33 +29,33 @@ import type { @Injectable() export class WebAuthnService { constructor( - @Inject(DI.redis) - private redisClient: Redis.Redis, - @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.userSecurityKeysRepository) private userSecurityKeysRepository: UserSecurityKeysRepository, - - private metaService: MetaService, ) { } @bindThis - public async getRelyingParty(): Promise<{ origin: string; rpId: string; rpName: string; rpIcon?: string; }> { - const instance = await this.metaService.fetch(); + public getRelyingParty(): { origin: string; rpId: string; rpName: string; rpIcon?: string; } { return { origin: this.config.url, rpId: this.config.hostname, - rpName: instance.name ?? this.config.host, - rpIcon: instance.iconUrl ?? undefined, + rpName: this.meta.name ?? this.config.host, + rpIcon: this.meta.iconUrl ?? undefined, }; } @bindThis public async initiateRegistration(userId: MiUser['id'], userName: string, userDisplayName?: string): Promise { - const relyingParty = await this.getRelyingParty(); + const relyingParty = this.getRelyingParty(); const keys = await this.userSecurityKeysRepository.findBy({ userId: userId, }); @@ -104,7 +102,7 @@ export class WebAuthnService { await this.redisClient.del(`webauthn:challenge:${userId}`); - const relyingParty = await this.getRelyingParty(); + const relyingParty = this.getRelyingParty(); let verification; try { @@ -143,7 +141,7 @@ export class WebAuthnService { @bindThis public async initiateAuthentication(userId: MiUser['id']): Promise { - const relyingParty = await this.getRelyingParty(); + const relyingParty = this.getRelyingParty(); const keys = await this.userSecurityKeysRepository.findBy({ userId: userId, }); @@ -166,6 +164,86 @@ export class WebAuthnService { return authenticationOptions; } + /** + * Initiate Passkey Auth (Without specifying user) + * @returns authenticationOptions + */ + @bindThis + public async initiateSignInWithPasskeyAuthentication(context: string): Promise { + const relyingParty = await this.getRelyingParty(); + + const authenticationOptions = await generateAuthenticationOptions({ + rpID: relyingParty.rpId, + userVerification: 'preferred', + }); + + await this.redisClient.setex(`webauthn:challenge:${context}`, 90, authenticationOptions.challenge); + + return authenticationOptions; + } + + /** + * Verify Webauthn AuthenticationCredential + * @throws IdentifiableError + * @returns If the challenge is successful, return the user ID. Otherwise, return null. + */ + @bindThis + public async verifySignInWithPasskeyAuthentication(context: string, response: AuthenticationResponseJSON): Promise { + const challenge = await this.redisClient.get(`webauthn:challenge:${context}`); + + if (!challenge) { + throw new IdentifiableError('2d16e51c-007b-4edd-afd2-f7dd02c947f6', `challenge '${context}' not found`); + } + + await this.redisClient.del(`webauthn:challenge:${context}`); + + const key = await this.userSecurityKeysRepository.findOneBy({ + id: response.id, + }); + + if (!key) { + throw new IdentifiableError('36b96a7d-b547-412d-aeed-2d611cdc8cdc', 'Unknown Webauthn key'); + } + + const relyingParty = await this.getRelyingParty(); + + let verification; + try { + verification = await verifyAuthenticationResponse({ + response: response, + expectedChallenge: challenge, + expectedOrigin: relyingParty.origin, + expectedRPID: relyingParty.rpId, + authenticator: { + credentialID: key.id, + credentialPublicKey: Buffer.from(key.publicKey, 'base64url'), + counter: key.counter, + transports: key.transports ? key.transports as AuthenticatorTransportFuture[] : undefined, + }, + requireUserVerification: true, + }); + } catch (error) { + throw new IdentifiableError('b18c89a7-5b5e-4cec-bb5b-0419f332d430', `verification failed: ${error}`); + } + + const { verified, authenticationInfo } = verification; + + if (!verified) { + return null; + } + + await this.userSecurityKeysRepository.update({ + id: response.id, + }, { + lastUsed: new Date(), + counter: authenticationInfo.newCounter, + credentialDeviceType: authenticationInfo.credentialDeviceType, + credentialBackedUp: authenticationInfo.credentialBackedUp, + }); + + return key.userId; + } + @bindThis public async verifyAuthentication(userId: MiUser['id'], response: AuthenticationResponseJSON): Promise { const challenge = await this.redisClient.get(`webauthn:challenge:${userId}`); @@ -209,7 +287,7 @@ export class WebAuthnService { } } - const relyingParty = await this.getRelyingParty(); + const relyingParty = this.getRelyingParty(); let verification; try { diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts new file mode 100644 index 0000000000..4c45b95a64 --- /dev/null +++ b/packages/backend/src/core/WebhookTestService.ts @@ -0,0 +1,451 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { Packed } from '@/misc/json-schema.js'; +import { type WebhookEventTypes } from '@/models/Webhook.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; +import { QueueService } from '@/core/QueueService.js'; + +const oneDayMillis = 24 * 60 * 60 * 1000; + +type AbuseUserReportDto = Omit & { + targetUser: Packed<'UserLite'> | null, + reporter: Packed<'UserLite'> | null, + assignee: Packed<'UserLite'> | null, +}; + +function generateAbuseReport(override?: Partial): AbuseUserReportDto { + const result: MiAbuseUserReport = { + id: 'dummy-abuse-report1', + targetUserId: 'dummy-target-user', + targetUser: null, + reporterId: 'dummy-reporter-user', + reporter: null, + assigneeId: null, + assignee: null, + resolved: false, + forwarded: false, + comment: 'This is a dummy report for testing purposes.', + targetUserHost: null, + reporterHost: null, + resolvedAs: null, + moderationNote: 'foo', + ...override, + }; + + return { + ...result, + targetUser: result.targetUser ? toPackedUserLite(result.targetUser) : null, + reporter: result.reporter ? toPackedUserLite(result.reporter) : null, + assignee: result.assignee ? toPackedUserLite(result.assignee) : null, + }; +} + +function generateDummyUser(override?: Partial): MiUser { + return { + id: 'dummy-user-1', + updatedAt: new Date(Date.now() - oneDayMillis * 7), + lastFetchedAt: new Date(Date.now() - oneDayMillis * 5), + lastActiveDate: new Date(Date.now() - oneDayMillis * 3), + hideOnlineStatus: false, + username: 'dummy1', + usernameLower: 'dummy1', + name: 'DummyUser1', + followersCount: 10, + followingCount: 5, + movedToUri: null, + movedAt: null, + alsoKnownAs: null, + notesCount: 30, + avatarId: null, + avatar: null, + bannerId: null, + banner: null, + avatarUrl: null, + bannerUrl: null, + avatarBlurhash: null, + bannerBlurhash: null, + avatarDecorations: [], + tags: [], + isSuspended: false, + isLocked: false, + isBot: false, + isCat: true, + isRoot: false, + isExplorable: true, + isHibernated: false, + isDeleted: false, + emojis: [], + score: 0, + host: null, + inbox: null, + sharedInbox: null, + featured: null, + uri: null, + followersUri: null, + token: null, + ...override, + }; +} + +function generateDummyNote(override?: Partial): MiNote { + return { + id: 'dummy-note-1', + replyId: null, + reply: null, + renoteId: null, + renote: null, + threadId: null, + text: 'This is a dummy note for testing purposes.', + name: null, + cw: null, + userId: 'dummy-user-1', + user: null, + localOnly: true, + reactionAcceptance: 'likeOnly', + renoteCount: 10, + repliesCount: 5, + clippedCount: 0, + reactions: {}, + visibility: 'public', + uri: null, + url: null, + fileIds: [], + attachedFileTypes: [], + visibleUserIds: [], + mentions: [], + mentionedRemoteUsers: '[]', + reactionAndUserPairCache: [], + emojis: [], + tags: [], + hasPoll: false, + channelId: null, + channel: null, + userHost: null, + replyUserId: null, + replyUserHost: null, + renoteUserId: null, + renoteUserHost: null, + ...override, + }; +} + +function toPackedNote(note: MiNote, detail = true, override?: Packed<'Note'>): Packed<'Note'> { + return { + id: note.id, + createdAt: new Date().toISOString(), + deletedAt: null, + text: note.text, + cw: note.cw, + userId: note.userId, + user: toPackedUserLite(note.user ?? generateDummyUser()), + replyId: note.replyId, + renoteId: note.renoteId, + isHidden: false, + visibility: note.visibility, + mentions: note.mentions, + visibleUserIds: note.visibleUserIds, + fileIds: note.fileIds, + files: [], + tags: note.tags, + poll: null, + emojis: note.emojis, + channelId: note.channelId, + channel: note.channel, + localOnly: note.localOnly, + reactionAcceptance: note.reactionAcceptance, + reactionEmojis: {}, + reactions: {}, + reactionCount: 0, + renoteCount: note.renoteCount, + repliesCount: note.repliesCount, + uri: note.uri ?? undefined, + url: note.url ?? undefined, + reactionAndUserPairCache: note.reactionAndUserPairCache, + ...(detail ? { + clippedCount: note.clippedCount, + reply: note.reply ? toPackedNote(note.reply, false) : null, + renote: note.renote ? toPackedNote(note.renote, true) : null, + myReaction: null, + } : {}), + ...override, + }; +} + +function toPackedUserLite(user: MiUser, override?: Packed<'UserLite'>): Packed<'UserLite'> { + return { + id: user.id, + name: user.name, + username: user.username, + host: user.host, + avatarUrl: user.avatarUrl, + avatarBlurhash: user.avatarBlurhash, + avatarDecorations: user.avatarDecorations.map(it => ({ + id: it.id, + angle: it.angle, + flipH: it.flipH, + url: 'https://example.com/dummy-image001.png', + offsetX: it.offsetX, + offsetY: it.offsetY, + })), + isBot: user.isBot, + isCat: user.isCat, + emojis: user.emojis, + onlineStatus: 'active', + badgeRoles: [], + ...override, + }; +} + +function toPackedUserDetailedNotMe(user: MiUser, override?: Packed<'UserDetailedNotMe'>): Packed<'UserDetailedNotMe'> { + return { + ...toPackedUserLite(user), + url: null, + uri: null, + movedTo: null, + alsoKnownAs: [], + createdAt: new Date().toISOString(), + updatedAt: user.updatedAt?.toISOString() ?? null, + lastFetchedAt: user.lastFetchedAt?.toISOString() ?? null, + bannerUrl: user.bannerUrl, + bannerBlurhash: user.bannerBlurhash, + isLocked: user.isLocked, + isSilenced: false, + isSuspended: user.isSuspended, + description: null, + location: null, + birthday: null, + lang: null, + fields: [], + verifiedLinks: [], + followersCount: user.followersCount, + followingCount: user.followingCount, + notesCount: user.notesCount, + pinnedNoteIds: [], + pinnedNotes: [], + pinnedPageId: null, + pinnedPage: null, + publicReactions: true, + followersVisibility: 'public', + followingVisibility: 'public', + twoFactorEnabled: false, + usePasswordLessLogin: false, + securityKeys: false, + roles: [], + memo: null, + moderationNote: undefined, + isFollowing: false, + isFollowed: false, + hasPendingFollowRequestFromYou: false, + hasPendingFollowRequestToYou: false, + isBlocking: false, + isBlocked: false, + isMuted: false, + isRenoteMuted: false, + notify: 'none', + withReplies: true, + ...override, + }; +} + +const dummyUser1 = generateDummyUser(); +const dummyUser2 = generateDummyUser({ + id: 'dummy-user-2', + updatedAt: new Date(Date.now() - oneDayMillis * 30), + lastFetchedAt: new Date(Date.now() - oneDayMillis), + lastActiveDate: new Date(Date.now() - oneDayMillis), + username: 'dummy2', + usernameLower: 'dummy2', + name: 'DummyUser2', + followersCount: 40, + followingCount: 50, + notesCount: 900, +}); +const dummyUser3 = generateDummyUser({ + id: 'dummy-user-3', + updatedAt: new Date(Date.now() - oneDayMillis * 15), + lastFetchedAt: new Date(Date.now() - oneDayMillis * 2), + lastActiveDate: new Date(Date.now() - oneDayMillis * 2), + username: 'dummy3', + usernameLower: 'dummy3', + name: 'DummyUser3', + followersCount: 60, + followingCount: 70, + notesCount: 15900, +}); + +@Injectable() +export class WebhookTestService { + public static NoSuchWebhookError = class extends Error { + }; + + constructor( + private userWebhookService: UserWebhookService, + private systemWebhookService: SystemWebhookService, + private queueService: QueueService, + ) { + } + + /** + * UserWebhookのテスト送信を行う. + * 送信されるペイロードはいずれもダミーの値で、実際にはデータベース上に存在しない. + * + * また、この関数経由で送信されるWebhookは以下の設定を無視する. + * - Webhookそのものの有効・無効設定(active) + * - 送信対象イベント(on)に関する設定 + */ + @bindThis + public async testUserWebhook( + params: { + webhookId: MiWebhook['id'], + type: WebhookEventTypes, + override?: Partial>, + }, + sender: MiUser | null, + ) { + const webhooks = await this.userWebhookService.fetchWebhooks({ ids: [params.webhookId] }) + .then(it => it.filter(it => it.userId === sender?.id)); + if (webhooks.length === 0) { + throw new WebhookTestService.NoSuchWebhookError(); + } + + const webhook = webhooks[0]; + const send = (contents: unknown) => { + const merged = { + ...webhook, + ...params.override, + }; + + // テスト目的なのでUserWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図). + // また、Jobの試行回数も1回だけ. + this.queueService.userWebhookDeliver(merged, params.type, contents, { attempts: 1 }); + }; + + const dummyNote1 = generateDummyNote({ + userId: dummyUser1.id, + user: dummyUser1, + }); + const dummyReply1 = generateDummyNote({ + id: 'dummy-reply-1', + replyId: dummyNote1.id, + reply: dummyNote1, + userId: dummyUser1.id, + user: dummyUser1, + }); + const dummyRenote1 = generateDummyNote({ + id: 'dummy-renote-1', + renoteId: dummyNote1.id, + renote: dummyNote1, + userId: dummyUser2.id, + user: dummyUser2, + text: null, + }); + const dummyMention1 = generateDummyNote({ + id: 'dummy-mention-1', + userId: dummyUser1.id, + user: dummyUser1, + text: `@${dummyUser2.username} This is a mention to you.`, + mentions: [dummyUser2.id], + }); + + switch (params.type) { + case 'note': { + send(toPackedNote(dummyNote1)); + break; + } + case 'reply': { + send(toPackedNote(dummyReply1)); + break; + } + case 'renote': { + send(toPackedNote(dummyRenote1)); + break; + } + case 'mention': { + send(toPackedNote(dummyMention1)); + break; + } + case 'follow': { + send(toPackedUserDetailedNotMe(dummyUser1)); + break; + } + case 'followed': { + send(toPackedUserLite(dummyUser2)); + break; + } + case 'unfollow': { + send(toPackedUserDetailedNotMe(dummyUser3)); + break; + } + } + } + + /** + * SystemWebhookのテスト送信を行う. + * 送信されるペイロードはいずれもダミーの値で、実際にはデータベース上に存在しない. + * + * また、この関数経由で送信されるWebhookは以下の設定を無視する. + * - Webhookそのものの有効・無効設定(isActive) + * - 送信対象イベント(on)に関する設定 + */ + @bindThis + public async testSystemWebhook( + params: { + webhookId: MiSystemWebhook['id'], + type: SystemWebhookEventType, + override?: Partial>, + }, + ) { + const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ ids: [params.webhookId] }); + if (webhooks.length === 0) { + throw new WebhookTestService.NoSuchWebhookError(); + } + + const webhook = webhooks[0]; + const send = (contents: unknown) => { + const merged = { + ...webhook, + ...params.override, + }; + + // テスト目的なのでSystemWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図). + // また、Jobの試行回数も1回だけ. + this.queueService.systemWebhookDeliver(merged, params.type, contents, { attempts: 1 }); + }; + + switch (params.type) { + case 'abuseReport': { + send(generateAbuseReport({ + targetUserId: dummyUser1.id, + targetUser: dummyUser1, + reporterId: dummyUser2.id, + reporter: dummyUser2, + })); + break; + } + case 'abuseReportResolved': { + send(generateAbuseReport({ + targetUserId: dummyUser1.id, + targetUser: dummyUser1, + reporterId: dummyUser2.id, + reporter: dummyUser2, + assigneeId: dummyUser3.id, + assignee: dummyUser3, + resolved: true, + })); + break; + } + case 'userCreated': { + send(toPackedUserLite(dummyUser1)); + break; + } + } + } +} diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index f6b70ead44..4192e8659a 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -54,8 +54,8 @@ export class ApDbResolverService implements OnApplicationShutdown { private cacheService: CacheService, private apPersonService: ApPersonService, ) { - this.publicKeyCache = new MemoryKVCache(Infinity); - this.publicKeyByUserIdCache = new MemoryKVCache(Infinity); + this.publicKeyCache = new MemoryKVCache(1000 * 60 * 60 * 12); // 12h + this.publicKeyByUserIdCache = new MemoryKVCache(1000 * 60 * 60 * 12); // 12h } @bindThis diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index e2164fec1d..376c9c0151 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -17,14 +17,13 @@ import { NoteCreateService } from '@/core/NoteCreateService.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { AppLockService } from '@/core/AppLockService.js'; import type Logger from '@/logger.js'; -import { MetaService } from '@/core/MetaService.js'; import { IdService } from '@/core/IdService.js'; import { StatusError } from '@/misc/status-error.js'; import { UtilityService } from '@/core/UtilityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { QueueService } from '@/core/QueueService.js'; -import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/_.js'; +import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository, MiMeta } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import type { MiRemoteUser } from '@/models/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; @@ -48,6 +47,9 @@ export class ApInboxService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -64,7 +66,6 @@ export class ApInboxService { private noteEntityService: NoteEntityService, private utilityService: UtilityService, private idService: IdService, - private metaService: MetaService, private abuseReportService: AbuseReportService, private userFollowingService: UserFollowingService, private apAudienceService: ApAudienceService, @@ -289,9 +290,8 @@ export class ApInboxService { return; } - // アナウンス先をブロックしてたら中断 - const meta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(meta.blockedHosts, this.utilityService.extractDbHost(uri))) return; + // アナウンス先が許可されているかチェック + if (!this.utilityService.isFederationAllowedUri(uri)) return; const unlock = await this.appLockService.getApLock(uri); diff --git a/packages/backend/src/core/activitypub/ApMfmService.ts b/packages/backend/src/core/activitypub/ApMfmService.ts index ab75b9abbd..4036d2794a 100644 --- a/packages/backend/src/core/activitypub/ApMfmService.ts +++ b/packages/backend/src/core/activitypub/ApMfmService.ts @@ -25,7 +25,7 @@ export class ApMfmService { } @bindThis - public getNoteHtml(note: MiNote, apAppend?: string) { + public getNoteHtml(note: Pick, apAppend?: string) { let noMisskeyContent = false; const srcMfm = (note.text ?? '') + (apAppend ?? ''); diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 98e944f347..fba8947f03 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -494,6 +494,7 @@ export class ApRendererService { name: user.name, summary: profile.description ? this.mfmService.toHtml(mfm.parse(profile.description)) : null, _misskey_summary: profile.description, + _misskey_followedMessage: profile.followedMessage, icon: avatar ? this.renderImage(avatar) : null, image: banner ? this.renderImage(banner) : null, tag, diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index 93ac8ce9a7..c7d19adfd5 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -6,6 +6,7 @@ import * as crypto from 'node:crypto'; import { URL } from 'node:url'; import { Inject, Injectable } from '@nestjs/common'; +import { Window } from 'happy-dom'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { MiUser } from '@/models/User.js'; @@ -180,7 +181,8 @@ export class ApRequestService { * @param url URL to fetch */ @bindThis - public async signedGet(url: string, user: { id: MiUser['id'] }): Promise { + public async signedGet(url: string, user: { id: MiUser['id'] }, followAlternate?: boolean): Promise { + const _followAlternate = followAlternate ?? true; const keypair = await this.userKeypairService.getUserKeypair(user.id); const req = ApRequestCreator.createSignedGet({ @@ -198,9 +200,58 @@ export class ApRequestService { headers: req.request.headers, }, { throwErrorWhenResponseNotOk: true, - validators: [validateContentTypeSetAsActivityPub], }); + //#region リクエスト先がhtmlかつactivity+jsonへのalternate linkタグがあるとき + const contentType = res.headers.get('content-type'); + + if ( + res.ok && + (contentType ?? '').split(';')[0].trimEnd().toLowerCase() === 'text/html' && + _followAlternate === true + ) { + const html = await res.text(); + const { window, happyDOM } = new Window({ + settings: { + disableJavaScriptEvaluation: true, + disableJavaScriptFileLoading: true, + disableCSSFileLoading: true, + disableComputedStyleRendering: true, + handleDisabledFileLoadingAsSuccess: true, + navigation: { + disableMainFrameNavigation: true, + disableChildFrameNavigation: true, + disableChildPageNavigation: true, + disableFallbackToSetURL: true, + }, + timer: { + maxTimeout: 0, + maxIntervalTime: 0, + maxIntervalIterations: 0, + }, + }, + }); + const document = window.document; + try { + document.documentElement.innerHTML = html; + + const alternate = document.querySelector('head > link[rel="alternate"][type="application/activity+json"]'); + if (alternate) { + const href = alternate.getAttribute('href'); + if (href) { + return await this.signedGet(href, user, false); + } + } + } catch (e) { + // something went wrong parsing the HTML, ignore the whole thing + } finally { + happyDOM.close().catch(err => {}); + } + } + //#endregion + + validateContentTypeSetAsActivityPub(res); + return await res.json(); } } diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index bb3c40f093..ca35608d9b 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -7,9 +7,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull, Not } from 'typeorm'; import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; -import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; +import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository, MiMeta } from '@/models/_.js'; import type { Config } from '@/config.js'; -import { MetaService } from '@/core/MetaService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { DI } from '@/di-symbols.js'; import { UtilityService } from '@/core/UtilityService.js'; @@ -29,6 +28,7 @@ export class Resolver { constructor( private config: Config, + private meta: MiMeta, private usersRepository: UsersRepository, private notesRepository: NotesRepository, private pollsRepository: PollsRepository, @@ -36,7 +36,6 @@ export class Resolver { private followRequestsRepository: FollowRequestsRepository, private utilityService: UtilityService, private instanceActorService: InstanceActorService, - private metaService: MetaService, private apRequestService: ApRequestService, private httpRequestService: HttpRequestService, private apRendererService: ApRendererService, @@ -94,8 +93,7 @@ export class Resolver { return await this.resolveLocal(value); } - const meta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(meta.blockedHosts, host)) { + if (!this.utilityService.isFederationAllowedHost(host)) { throw new Error('Instance is blocked'); } @@ -178,6 +176,9 @@ export class ApResolverService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -195,7 +196,6 @@ export class ApResolverService { private utilityService: UtilityService, private instanceActorService: InstanceActorService, - private metaService: MetaService, private apRequestService: ApRequestService, private httpRequestService: HttpRequestService, private apRendererService: ApRendererService, @@ -208,6 +208,7 @@ export class ApResolverService { public createResolver(): Resolver { return new Resolver( this.config, + this.meta, this.usersRepository, this.notesRepository, this.pollsRepository, @@ -215,7 +216,6 @@ export class ApResolverService { this.followRequestsRepository, this.utilityService, this.instanceActorService, - this.metaService, this.apRequestService, this.httpRequestService, this.apRendererService, diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts index feb8c42c56..3dd85b9b86 100644 --- a/packages/backend/src/core/activitypub/misc/contexts.ts +++ b/packages/backend/src/core/activitypub/misc/contexts.ts @@ -554,6 +554,7 @@ const extension_context_definition = { '_misskey_reaction': 'misskey:_misskey_reaction', '_misskey_votes': 'misskey:_misskey_votes', '_misskey_summary': 'misskey:_misskey_summary', + '_misskey_followedMessage': 'misskey:_misskey_followedMessage', 'isCat': 'misskey:isCat', // vcard vcard: 'http://www.w3.org/2006/vcard/ns#', diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts index 3691967270..e7ece87b01 100644 --- a/packages/backend/src/core/activitypub/models/ApImageService.ts +++ b/packages/backend/src/core/activitypub/models/ApImageService.ts @@ -5,10 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository } from '@/models/_.js'; +import type { DriveFilesRepository, MiMeta } from '@/models/_.js'; import type { MiRemoteUser } from '@/models/User.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; -import { MetaService } from '@/core/MetaService.js'; import { truncate } from '@/misc/truncate.js'; import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/const.js'; import { DriveService } from '@/core/DriveService.js'; @@ -24,10 +23,12 @@ export class ApImageService { private logger: Logger; constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.driveFilesRepository) private driveFilesRepository: DriveFilesRepository, - private metaService: MetaService, private apResolverService: ApResolverService, private driveService: DriveService, private apLoggerService: ApLoggerService, @@ -63,12 +64,10 @@ export class ApImageService { this.logger.info(`Creating the Image: ${image.url}`); - const instance = await this.metaService.fetch(); - // Cache if remote file cache is on AND either // 1. remote sensitive file is also on // 2. or the image is not sensitive - const shouldBeCached = instance.cacheRemoteFiles && (instance.cacheRemoteSensitiveFiles || !image.sensitive); + const shouldBeCached = this.meta.cacheRemoteFiles && (this.meta.cacheRemoteSensitiveFiles || !image.sensitive); const file = await this.driveService.uploadFromUrl({ url: image.url, diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index fc7aa1e0b9..2d333b3634 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -6,13 +6,12 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { PollsRepository, EmojisRepository } from '@/models/_.js'; +import type { PollsRepository, EmojisRepository, MiMeta } from '@/models/_.js'; import type { Config } from '@/config.js'; import type { MiRemoteUser } from '@/models/User.js'; import type { MiNote } from '@/models/Note.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import type { MiEmoji } from '@/models/Emoji.js'; -import { MetaService } from '@/core/MetaService.js'; import { AppLockService } from '@/core/AppLockService.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; import { NoteCreateService } from '@/core/NoteCreateService.js'; @@ -46,6 +45,9 @@ export class ApNoteService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.pollsRepository) private pollsRepository: PollsRepository, @@ -65,7 +67,6 @@ export class ApNoteService { private apMentionService: ApMentionService, private apImageService: ApImageService, private apQuestionService: ApQuestionService, - private metaService: MetaService, private appLockService: AppLockService, private pollService: PollService, private noteCreateService: NoteCreateService, @@ -78,9 +79,10 @@ export class ApNoteService { @bindThis public validateNote(object: IObject, uri: string): Error | null { const expectHost = this.utilityService.extractDbHost(uri); + const apType = getApType(object); - if (!validPost.includes(getApType(object))) { - return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${getApType(object)}`); + if (apType == null || !validPost.includes(apType)) { + return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${apType ?? 'undefined'}`); } if (object.id && this.utilityService.extractDbHost(object.id) !== expectHost) { @@ -181,7 +183,7 @@ export class ApNoteService { /** * 禁止ワードチェック */ - const hasProhibitedWords = await this.noteCreateService.checkProhibitedWordsContain({ cw, text, pollChoices: poll?.choices }); + const hasProhibitedWords = this.noteCreateService.checkProhibitedWordsContain({ cw, text, pollChoices: poll?.choices }); if (hasProhibitedWords) { throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Note contains prohibited words'); } @@ -334,9 +336,7 @@ export class ApNoteService { public async resolveNote(value: string | IObject, options: { sentFrom?: URL, resolver?: Resolver } = {}): Promise { const uri = getApId(value); - // ブロックしていたら中断 - const meta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(meta.blockedHosts, this.utilityService.extractDbHost(uri))) { + if (!this.utilityService.isFederationAllowedUri(uri)) { throw new StatusError('blocked host', 451); } diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 398c8695d2..e042a85782 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -8,7 +8,7 @@ import promiseLimit from 'promise-limit'; import { DataSource } from 'typeorm'; import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; +import type { FollowingsRepository, InstancesRepository, MiMeta, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { MiUser } from '@/models/User.js'; @@ -34,7 +34,7 @@ import { StatusError } from '@/misc/status-error.js'; import type { UtilityService } from '@/core/UtilityService.js'; import type { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; +import { RoleService } from '@/core/RoleService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import type { AccountMoveService } from '@/core/AccountMoveService.js'; import { checkHttps } from '@/misc/check-https.js'; @@ -45,9 +45,9 @@ import type { ApNoteService } from './ApNoteService.js'; import type { ApMfmService } from '../ApMfmService.js'; import type { ApResolverService, Resolver } from '../ApResolverService.js'; import type { ApLoggerService } from '../ApLoggerService.js'; -// eslint-disable-next-line @typescript-eslint/consistent-type-imports + import type { ApImageService } from './ApImageService.js'; -import type { IActor, IObject } from '../type.js'; +import type { IActor, ICollection, IObject, IOrderedCollection } from '../type.js'; const nameLength = 128; const summaryLength = 2048; @@ -61,7 +61,6 @@ export class ApPersonService implements OnModuleInit { private driveFileEntityService: DriveFileEntityService; private idService: IdService; private globalEventService: GlobalEventService; - private metaService: MetaService; private federatedInstanceService: FederatedInstanceService; private fetchInstanceMetadataService: FetchInstanceMetadataService; private cacheService: CacheService; @@ -83,6 +82,9 @@ export class ApPersonService implements OnModuleInit { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.db) private db: DataSource, @@ -100,6 +102,8 @@ export class ApPersonService implements OnModuleInit { @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, + + private roleService: RoleService, ) { } @@ -109,7 +113,6 @@ export class ApPersonService implements OnModuleInit { this.driveFileEntityService = this.moduleRef.get('DriveFileEntityService'); this.idService = this.moduleRef.get('IdService'); this.globalEventService = this.moduleRef.get('GlobalEventService'); - this.metaService = this.moduleRef.get('MetaService'); this.federatedInstanceService = this.moduleRef.get('FederatedInstanceService'); this.fetchInstanceMetadataService = this.moduleRef.get('FetchInstanceMetadataService'); this.cacheService = this.moduleRef.get('CacheService'); @@ -238,6 +241,11 @@ export class ApPersonService implements OnModuleInit { return this.apImageService.resolveImage(user, img).catch(() => null); })); + if (((avatar != null && avatar.id != null) || (banner != null && banner.id != null)) + && !(await this.roleService.getUserPolicies(user.id)).canUpdateBioMedia) { + return {}; + } + /* we don't want to return nulls on errors! if the database fields are already null, nothing changes; if the database has old @@ -288,6 +296,21 @@ export class ApPersonService implements OnModuleInit { const isBot = getApType(object) === 'Service' || getApType(object) === 'Application'; + const [followingVisibility, followersVisibility] = await Promise.all( + [ + this.isPublicCollection(person.following, resolver), + this.isPublicCollection(person.followers, resolver), + ].map((p): Promise<'public' | 'private'> => p + .then(isPublic => isPublic ? 'public' : 'private') + .catch(err => { + if (!(err instanceof StatusError) || err.isRetryable) { + this.logger.error('error occurred while fetching following/followers collection', { stack: err }); + } + return 'private'; + }), + ), + ); + const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); const url = getOneApHrefNullable(person.url); @@ -347,8 +370,11 @@ export class ApPersonService implements OnModuleInit { await transactionalEntityManager.save(new MiUserProfile({ userId: user.id, description: _description, + followedMessage: person._misskey_followedMessage != null ? truncate(person._misskey_followedMessage, 256) : null, url, fields, + followingVisibility, + followersVisibility, birthday: bday?.[0] ?? null, location: person['vcard:Address'] ?? null, userHost: host, @@ -382,10 +408,10 @@ export class ApPersonService implements OnModuleInit { this.cacheService.uriPersonCache.set(user.uri, user); // Register host - this.federatedInstanceService.fetch(host).then(async i => { + this.federatedInstanceService.fetch(host).then(i => { this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); this.fetchInstanceMetadataService.fetchInstanceMetadata(i); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.newUser(i.host); } }); @@ -456,6 +482,23 @@ export class ApPersonService implements OnModuleInit { const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32); + const [followingVisibility, followersVisibility] = await Promise.all( + [ + this.isPublicCollection(person.following, resolver), + this.isPublicCollection(person.followers, resolver), + ].map((p): Promise<'public' | 'private' | undefined> => p + .then(isPublic => isPublic ? 'public' : 'private') + .catch(err => { + if (!(err instanceof StatusError) || err.isRetryable) { + this.logger.error('error occurred while fetching following/followers collection', { stack: err }); + // Do not update the visibiility on transient errors. + return undefined; + } + return 'private'; + }), + ), + ); + const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); const url = getOneApHrefNullable(person.url); @@ -524,6 +567,9 @@ export class ApPersonService implements OnModuleInit { url, fields, description: _description, + followedMessage: person._misskey_followedMessage != null ? truncate(person._misskey_followedMessage, 256) : null, + followingVisibility, + followersVisibility, birthday: bday?.[0] ?? null, location: person['vcard:Address'] ?? null, }); @@ -695,4 +741,16 @@ export class ApPersonService implements OnModuleInit { return 'ok'; } + + @bindThis + private async isPublicCollection(collection: string | ICollection | IOrderedCollection | undefined, resolver: Resolver): Promise { + if (collection) { + const resolved = await resolver.resolveCollection(collection); + if (resolved.first || (resolved as ICollection).items || (resolved as IOrderedCollection).orderedItems) { + return true; + } + } + + return false; + } } diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts index 4fae1e897b..73004d10b0 100644 --- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts +++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts @@ -74,10 +74,10 @@ export class ApQuestionService { //#region このサーバーに既に登録されているか const note = await this.notesRepository.findOneBy({ uri }); - if (note == null) throw new Error('Question is not registed'); + if (note == null) throw new Error('Question is not registered'); const poll = await this.pollsRepository.findOneBy({ noteId: note.id }); - if (poll == null) throw new Error('Question is not registed'); + if (poll == null) throw new Error('Question is not registered'); //#endregion // resolve new Question object diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 5b6c6c8ca6..154965b9d5 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -13,6 +13,7 @@ export interface IObject { name?: string | null; summary?: string; _misskey_summary?: string; + _misskey_followedMessage?: string | null; published?: string; cc?: ApObject; to?: ApObject; @@ -60,11 +61,14 @@ export function getApId(value: string | IObject): string { /** * Get ActivityStreams Object type + * + * タイプ判定ができなかった場合に、あえてエラーではなくnullを返すようにしている。 + * 詳細: https://github.com/misskey-dev/misskey/issues/14239 */ -export function getApType(value: IObject): string { +export function getApType(value: IObject): string | null { if (typeof value.type === 'string') return value.type; if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0]; - throw new Error('cannot detect type'); + return null; } export function getOneApHrefNullable(value: ApObject | undefined): string | undefined { @@ -97,19 +101,23 @@ export interface IActivity extends IObject { export interface ICollection extends IObject { type: 'Collection'; totalItems: number; - items: ApObject; + first?: IObject | string; + items?: ApObject; } export interface IOrderedCollection extends IObject { type: 'OrderedCollection'; totalItems: number; - orderedItems: ApObject; + first?: IObject | string; + orderedItems?: ApObject; } export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event']; -export const isPost = (object: IObject): object is IPost => - validPost.includes(getApType(object)); +export const isPost = (object: IObject): object is IPost => { + const type = getApType(object); + return type != null && validPost.includes(type); +}; export interface IPost extends IObject { type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event'; @@ -156,8 +164,10 @@ export const isTombstone = (object: IObject): object is ITombstone => export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application']; -export const isActor = (object: IObject): object is IActor => - validActor.includes(getApType(object)); +export const isActor = (object: IObject): object is IActor => { + const type = getApType(object); + return type != null && validActor.includes(type); +}; export interface IActor extends IObject { type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application'; @@ -240,12 +250,16 @@ export interface IKey extends IObject { publicKeyPem: string | Buffer; } +export const validDocumentTypes = ['Audio', 'Document', 'Image', 'Page', 'Video']; + export interface IApDocument extends IObject { type: 'Audio' | 'Document' | 'Image' | 'Page' | 'Video'; } -export const isDocument = (object: IObject): object is IApDocument => - ['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object)); +export const isDocument = (object: IObject): object is IApDocument => { + const type = getApType(object); + return type != null && validDocumentTypes.includes(type); +}; export interface IApImage extends IApDocument { type: 'Image'; @@ -323,7 +337,10 @@ export const isAccept = (object: IObject): object is IAccept => getApType(object export const isReject = (object: IObject): object is IReject => getApType(object) === 'Reject'; export const isAdd = (object: IObject): object is IAdd => getApType(object) === 'Add'; export const isRemove = (object: IObject): object is IRemove => getApType(object) === 'Remove'; -export const isLike = (object: IObject): object is ILike => getApType(object) === 'Like' || getApType(object) === 'EmojiReaction' || getApType(object) === 'EmojiReact'; +export const isLike = (object: IObject): object is ILike => { + const type = getApType(object); + return type != null && ['Like', 'EmojiReaction', 'EmojiReact'].includes(type); +}; export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce'; export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block'; export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag'; diff --git a/packages/backend/src/core/chart/charts/federation.ts b/packages/backend/src/core/chart/charts/federation.ts index c2329a2f73..c9b43cc66d 100644 --- a/packages/backend/src/core/chart/charts/federation.ts +++ b/packages/backend/src/core/chart/charts/federation.ts @@ -5,10 +5,9 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { FollowingsRepository, InstancesRepository } from '@/models/_.js'; +import type { FollowingsRepository, InstancesRepository, MiMeta } from '@/models/_.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; -import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import Chart from '../core.js'; import { ChartLoggerService } from '../ChartLoggerService.js'; @@ -24,13 +23,15 @@ export default class FederationChart extends Chart { // eslint-di @Inject(DI.db) private db: DataSource, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, @Inject(DI.instancesRepository) private instancesRepository: InstancesRepository, - private metaService: MetaService, private appLockService: AppLockService, private chartLoggerService: ChartLoggerService, ) { @@ -43,8 +44,6 @@ export default class FederationChart extends Chart { // eslint-di } protected async tickMinor(): Promise>> { - const meta = await this.metaService.fetch(); - const suspendedInstancesQuery = this.instancesRepository.createQueryBuilder('instance') .select('instance.host') .where('instance.suspensionState != \'none\''); @@ -65,21 +64,21 @@ export default class FederationChart extends Chart { // eslint-di this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(this.meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followerHost)') .where('following.followerHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followerHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(this.meta.blockedHosts.length === 0 ? '1=1' : 'following.followerHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followerHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), this.followingsRepository.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(this.meta.blockedHosts.length === 0 ? '1=1' : 'following.followeeHost NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) .setParameters(pubsubSubQuery.getParameters()) @@ -88,7 +87,7 @@ export default class FederationChart extends Chart { // eslint-di this.instancesRepository.createQueryBuilder('instance') .select('COUNT(instance.id)') .where(`instance.host IN (${ subInstancesQuery.getQuery() })`) - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(this.meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() @@ -96,7 +95,7 @@ export default class FederationChart extends Chart { // eslint-di this.instancesRepository.createQueryBuilder('instance') .select('COUNT(instance.id)') .where(`instance.host IN (${ pubInstancesQuery.getQuery() })`) - .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) + .andWhere(this.meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ALL(ARRAY[:...blocked])', { blocked: this.meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() diff --git a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts index a13c244c19..70ead890ab 100644 --- a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts +++ b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts @@ -53,6 +53,8 @@ export class AbuseUserReportEntityService { schema: 'UserDetailedNotMe', }) : null, forwarded: report.forwarded, + resolvedAs: report.resolvedAs, + moderationNote: report.moderationNote, }); } diff --git a/packages/backend/src/core/entities/FlashEntityService.ts b/packages/backend/src/core/entities/FlashEntityService.ts index d110f7afc6..7b0150f5b6 100644 --- a/packages/backend/src/core/entities/FlashEntityService.ts +++ b/packages/backend/src/core/entities/FlashEntityService.ts @@ -5,10 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { FlashsRepository, FlashLikesRepository } from '@/models/_.js'; -import { awaitAll } from '@/misc/prelude/await-all.js'; +import type { FlashLikesRepository, FlashsRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/Blocking.js'; import type { MiUser } from '@/models/User.js'; import type { MiFlash } from '@/models/Flash.js'; import { bindThis } from '@/decorators.js'; @@ -20,10 +18,8 @@ export class FlashEntityService { constructor( @Inject(DI.flashsRepository) private flashsRepository: FlashsRepository, - @Inject(DI.flashLikesRepository) private flashLikesRepository: FlashLikesRepository, - private userEntityService: UserEntityService, private idService: IdService, ) { @@ -34,24 +30,36 @@ export class FlashEntityService { src: MiFlash['id'] | MiFlash, me?: { id: MiUser['id'] } | null | undefined, hint?: { - packedUser?: Packed<'UserLite'> + packedUser?: Packed<'UserLite'>, + likedFlashIds?: MiFlash['id'][], }, ): Promise> { const meId = me ? me.id : null; const flash = typeof src === 'object' ? src : await this.flashsRepository.findOneByOrFail({ id: src }); - return await awaitAll({ + // { schema: 'UserDetailed' } すると無限ループするので注意 + const user = hint?.packedUser ?? await this.userEntityService.pack(flash.user ?? flash.userId, me); + + let isLiked = undefined; + if (meId) { + isLiked = hint?.likedFlashIds + ? hint.likedFlashIds.includes(flash.id) + : await this.flashLikesRepository.exists({ where: { flashId: flash.id, userId: meId } }); + } + + return { id: flash.id, createdAt: this.idService.parse(flash.id).date.toISOString(), updatedAt: flash.updatedAt.toISOString(), userId: flash.userId, - user: hint?.packedUser ?? this.userEntityService.pack(flash.user ?? flash.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意 + user: user, title: flash.title, summary: flash.summary, script: flash.script, + visibility: flash.visibility, likedCount: flash.likedCount, - isLiked: meId ? await this.flashLikesRepository.exists({ where: { flashId: flash.id, userId: meId } }) : undefined, - }); + isLiked: isLiked, + }; } @bindThis @@ -62,7 +70,19 @@ export class FlashEntityService { const _users = flashes.map(({ user, userId }) => user ?? userId); const _userMap = await this.userEntityService.packMany(_users, me) .then(users => new Map(users.map(u => [u.id, u]))); - return Promise.all(flashes.map(flash => this.pack(flash, me, { packedUser: _userMap.get(flash.userId) }))); + const _likedFlashIds = me + ? await this.flashLikesRepository.createQueryBuilder('flashLike') + .select('flashLike.flashId') + .where('flashLike.userId = :userId', { userId: me.id }) + .getRawMany<{ flashLike_flashId: string }>() + .then(likes => [...new Set(likes.map(like => like.flashLike_flashId))]) + : []; + return Promise.all( + flashes.map(flash => this.pack(flash, me, { + packedUser: _userMap.get(flash.userId), + likedFlashIds: _likedFlashIds, + })), + ); } } diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts index 9117b13914..284537b986 100644 --- a/packages/backend/src/core/entities/InstanceEntityService.ts +++ b/packages/backend/src/core/entities/InstanceEntityService.ts @@ -3,19 +3,22 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import type { Packed } from '@/misc/json-schema.js'; import type { MiInstance } from '@/models/Instance.js'; -import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import { UtilityService } from '@/core/UtilityService.js'; import { RoleService } from '@/core/RoleService.js'; import { MiUser } from '@/models/User.js'; +import { DI } from '@/di-symbols.js'; +import { MiMeta } from '@/models/_.js'; @Injectable() export class InstanceEntityService { constructor( - private metaService: MetaService, + @Inject(DI.meta) + private meta: MiMeta, + private roleService: RoleService, private utilityService: UtilityService, @@ -27,7 +30,6 @@ export class InstanceEntityService { instance: MiInstance, me?: { id: MiUser['id']; } | null | undefined, ): Promise> { - const meta = await this.metaService.fetch(); const iAmModerator = me ? await this.roleService.isModerator(me as MiUser) : false; return { @@ -41,7 +43,7 @@ export class InstanceEntityService { isNotResponding: instance.isNotResponding, isSuspended: instance.suspensionState !== 'none', suspensionState: instance.suspensionState, - isBlocked: this.utilityService.isBlockedHost(meta.blockedHosts, instance.host), + isBlocked: this.utilityService.isBlockedHost(this.meta.blockedHosts, instance.host), softwareName: instance.softwareName, softwareVersion: instance.softwareVersion, openRegistrations: instance.openRegistrations, @@ -49,7 +51,8 @@ export class InstanceEntityService { description: instance.description, maintainerName: instance.maintainerName, maintainerEmail: instance.maintainerEmail, - isSilenced: this.utilityService.isSilencedHost(meta.silencedHosts, instance.host), + isSilenced: this.utilityService.isSilencedHost(this.meta.silencedHosts, instance.host), + isMediaSilenced: this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, instance.host), iconUrl: instance.iconUrl, faviconUrl: instance.faviconUrl, themeColor: instance.themeColor, @@ -62,8 +65,9 @@ export class InstanceEntityService { @bindThis public packMany( instances: MiInstance[], + me?: { id: MiUser['id']; } | null | undefined, ) { - return Promise.all(instances.map(x => this.pack(x))); + return Promise.all(instances.map(x => this.pack(x, me))); } } diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 5dfec589e1..409dca3426 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -10,7 +10,6 @@ import type { Packed } from '@/misc/json-schema.js'; import type { MiMeta } from '@/models/Meta.js'; import type { AdsRepository } from '@/models/_.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; -import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; @@ -24,11 +23,13 @@ export class MetaEntityService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.adsRepository) private adsRepository: AdsRepository, private userEntityService: UserEntityService, - private metaService: MetaService, private instanceActorService: InstanceActorService, ) { } @@ -37,7 +38,7 @@ export class MetaEntityService { let instance = meta; if (!instance) { - instance = await this.metaService.fetch(); + instance = this.meta; } const ads = await this.adsRepository.createQueryBuilder('ads') @@ -50,6 +51,22 @@ export class MetaEntityService { })) .getMany(); + // クライアントの手間を減らすためあらかじめJSONに変換しておく + let defaultLightTheme = null; + let defaultDarkTheme = null; + if (instance.defaultLightTheme) { + try { + defaultLightTheme = JSON.stringify(JSON5.parse(instance.defaultLightTheme)); + } catch (e) { + } + } + if (instance.defaultDarkTheme) { + try { + defaultDarkTheme = JSON.stringify(JSON5.parse(instance.defaultDarkTheme)); + } catch (e) { + } + } + const packed: Packed<'MetaLite'> = { maintainerName: instance.maintainerName, maintainerEmail: instance.maintainerEmail, @@ -79,6 +96,7 @@ export class MetaEntityService { recaptchaSiteKey: instance.recaptchaSiteKey, enableTurnstile: instance.enableTurnstile, turnstileSiteKey: instance.turnstileSiteKey, + enableTestcaptcha: instance.enableTestcaptcha, swPublickey: instance.swPublicKey, themeColor: instance.themeColor, mascotImageUrl: instance.mascotImageUrl ?? '/assets/ai.png', @@ -90,9 +108,8 @@ export class MetaEntityService { backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, - // クライアントの手間を減らすためあらかじめJSONに変換しておく - defaultLightTheme: instance.defaultLightTheme ? JSON.stringify(JSON5.parse(instance.defaultLightTheme)) : null, - defaultDarkTheme: instance.defaultDarkTheme ? JSON.stringify(JSON5.parse(instance.defaultDarkTheme)) : null, + defaultLightTheme, + defaultDarkTheme, ads: ads.map(ad => ({ id: ad.id, url: ad.url, @@ -113,6 +130,8 @@ export class MetaEntityService { mediaProxy: this.config.mediaProxy, enableUrlPreview: instance.urlPreviewEnabled, + noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', + maxFileSize: this.config.maxFileSize, }; return packed; @@ -123,7 +142,7 @@ export class MetaEntityService { let instance = meta; if (!instance) { - instance = await this.metaService.fetch(); + instance = this.meta; } const packed = await this.pack(instance); diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 2cd092231c..c64e9151a7 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -11,11 +11,11 @@ import type { Packed } from '@/misc/json-schema.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { MiUser } from '@/models/User.js'; import type { MiNote } from '@/models/Note.js'; -import type { MiNoteReaction } from '@/models/NoteReaction.js'; -import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js'; +import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository, MiMeta } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { DebounceLoader } from '@/misc/loader.js'; import { IdService } from '@/core/IdService.js'; +import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; import type { OnModuleInit } from '@nestjs/common'; import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { ReactionService } from '../ReactionService.js'; @@ -28,12 +28,16 @@ export class NoteEntityService implements OnModuleInit { private driveFileEntityService: DriveFileEntityService; private customEmojiService: CustomEmojiService; private reactionService: ReactionService; + private reactionsBufferingService: ReactionsBufferingService; private idService: IdService; private noteLoader = new DebounceLoader(this.findNoteOrFail); constructor( private moduleRef: ModuleRef, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -59,6 +63,8 @@ export class NoteEntityService implements OnModuleInit { //private driveFileEntityService: DriveFileEntityService, //private customEmojiService: CustomEmojiService, //private reactionService: ReactionService, + //private reactionsBufferingService: ReactionsBufferingService, + //private idService: IdService, ) { } @@ -67,6 +73,7 @@ export class NoteEntityService implements OnModuleInit { this.driveFileEntityService = this.moduleRef.get('DriveFileEntityService'); this.customEmojiService = this.moduleRef.get('CustomEmojiService'); this.reactionService = this.moduleRef.get('ReactionService'); + this.reactionsBufferingService = this.moduleRef.get('ReactionsBufferingService'); this.idService = this.moduleRef.get('IdService'); } @@ -287,6 +294,7 @@ export class NoteEntityService implements OnModuleInit { skipHide?: boolean; withReactionAndUserPairCache?: boolean; _hint_?: { + bufferedReactions: Map; pairs: ([MiUser['id'], string])[] }> | null; myReactions: Map; packedFiles: Map | null>; packedUsers: Map> @@ -303,6 +311,15 @@ export class NoteEntityService implements OnModuleInit { const note = typeof src === 'object' ? src : await this.noteLoader.load(src); const host = note.userHost; + const bufferedReactions = opts._hint_?.bufferedReactions != null + ? (opts._hint_.bufferedReactions.get(note.id) ?? { deltas: {}, pairs: [] }) + : this.meta.enableReactionsBuffering + ? await this.reactionsBufferingService.get(note.id) + : { deltas: {}, pairs: [] }; + const reactions = this.reactionService.convertLegacyReactions(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions.deltas ?? {})); + + const reactionAndUserPairCache = note.reactionAndUserPairCache.concat(bufferedReactions.pairs.map(x => x.join('/'))); + let text = note.text; if (note.name && (note.url ?? note.uri)) { @@ -315,7 +332,7 @@ export class NoteEntityService implements OnModuleInit { : await this.channelsRepository.findOneBy({ id: note.channelId }) : null; - const reactionEmojiNames = Object.keys(note.reactions) + const reactionEmojiNames = Object.keys(reactions) .filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ .map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', '')); const packedFiles = options?._hint_?.packedFiles; @@ -334,10 +351,10 @@ export class NoteEntityService implements OnModuleInit { visibleUserIds: note.visibility === 'specified' ? note.visibleUserIds : undefined, renoteCount: note.renoteCount, repliesCount: note.repliesCount, - reactionCount: Object.values(note.reactions).reduce((a, b) => a + b, 0), - reactions: this.reactionService.convertLegacyReactions(note.reactions), + reactionCount: Object.values(reactions).reduce((a, b) => a + b, 0), + reactions: reactions, reactionEmojis: this.customEmojiService.populateEmojis(reactionEmojiNames, host), - reactionAndUserPairCache: opts.withReactionAndUserPairCache ? note.reactionAndUserPairCache : undefined, + reactionAndUserPairCache: opts.withReactionAndUserPairCache ? reactionAndUserPairCache : undefined, emojis: host != null ? this.customEmojiService.populateEmojis(note.emojis, host) : undefined, tags: note.tags.length > 0 ? note.tags : undefined, fileIds: note.fileIds, @@ -376,8 +393,12 @@ export class NoteEntityService implements OnModuleInit { poll: note.hasPoll ? this.populatePoll(note, meId) : undefined, - ...(meId && Object.keys(note.reactions).length > 0 ? { - myReaction: this.populateMyReaction(note, meId, options?._hint_), + ...(meId && Object.keys(reactions).length > 0 ? { + myReaction: this.populateMyReaction({ + id: note.id, + reactions: reactions, + reactionAndUserPairCache: reactionAndUserPairCache, + }, meId, options?._hint_), } : {}), } : {}), }); @@ -400,6 +421,8 @@ export class NoteEntityService implements OnModuleInit { ) { if (notes.length === 0) return []; + const bufferedReactions = this.meta.enableReactionsBuffering ? await this.reactionsBufferingService.getMany(notes.map(x => x.id)) : null; + const meId = me ? me.id : null; const myReactionsMap = new Map(); if (meId) { @@ -410,23 +433,33 @@ export class NoteEntityService implements OnModuleInit { for (const note of notes) { if (note.renote && (note.text == null && note.fileIds.length === 0)) { // pure renote - const reactionsCount = Object.values(note.renote.reactions).reduce((a, b) => a + b, 0); + const reactionsCount = Object.values(this.reactionsBufferingService.mergeReactions(note.renote.reactions, bufferedReactions?.get(note.renote.id)?.deltas ?? {})).reduce((a, b) => a + b, 0); if (reactionsCount === 0) { myReactionsMap.set(note.renote.id, null); - } else if (reactionsCount <= note.renote.reactionAndUserPairCache.length) { - const pair = note.renote.reactionAndUserPairCache.find(p => p.startsWith(meId)); - myReactionsMap.set(note.renote.id, pair ? pair.split('/')[1] : null); + } else if (reactionsCount <= note.renote.reactionAndUserPairCache.length + (bufferedReactions?.get(note.renote.id)?.pairs.length ?? 0)) { + const pairInBuffer = bufferedReactions?.get(note.renote.id)?.pairs.find(p => p[0] === meId); + if (pairInBuffer) { + myReactionsMap.set(note.renote.id, pairInBuffer[1]); + } else { + const pair = note.renote.reactionAndUserPairCache.find(p => p.startsWith(meId)); + myReactionsMap.set(note.renote.id, pair ? pair.split('/')[1] : null); + } } else { idsNeedFetchMyReaction.add(note.renote.id); } } else { if (note.id < oldId) { - const reactionsCount = Object.values(note.reactions).reduce((a, b) => a + b, 0); + const reactionsCount = Object.values(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions?.get(note.id)?.deltas ?? {})).reduce((a, b) => a + b, 0); if (reactionsCount === 0) { myReactionsMap.set(note.id, null); - } else if (reactionsCount <= note.reactionAndUserPairCache.length) { - const pair = note.reactionAndUserPairCache.find(p => p.startsWith(meId)); - myReactionsMap.set(note.id, pair ? pair.split('/')[1] : null); + } else if (reactionsCount <= note.reactionAndUserPairCache.length + (bufferedReactions?.get(note.id)?.pairs.length ?? 0)) { + const pairInBuffer = bufferedReactions?.get(note.id)?.pairs.find(p => p[0] === meId); + if (pairInBuffer) { + myReactionsMap.set(note.id, pairInBuffer[1]); + } else { + const pair = note.reactionAndUserPairCache.find(p => p.startsWith(meId)); + myReactionsMap.set(note.id, pair ? pair.split('/')[1] : null); + } } else { idsNeedFetchMyReaction.add(note.id); } @@ -461,6 +494,7 @@ export class NoteEntityService implements OnModuleInit { return await Promise.all(notes.map(n => this.pack(n, me, { ...options, _hint_: { + bufferedReactions, myReactions: myReactionsMap, packedFiles, packedUsers, diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index f393513510..dff6968f9c 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -59,7 +59,7 @@ export class NotificationEntityService implements OnModuleInit { async #packInternal ( src: T, meId: MiUser['id'], - // eslint-disable-next-line @typescript-eslint/ban-types + options: { checkValidNotifier?: boolean; }, @@ -159,9 +159,16 @@ export class NotificationEntityService implements OnModuleInit { ...(notification.type === 'roleAssigned' ? { role: role, } : {}), + ...(notification.type === 'followRequestAccepted' ? { + message: notification.message, + } : {}), ...(notification.type === 'achievementEarned' ? { achievement: notification.achievement, } : {}), + ...(notification.type === 'exportCompleted' ? { + exportedEntity: notification.exportedEntity, + fileId: notification.fileId, + } : {}), ...(notification.type === 'app' ? { body: notification.customBody, header: notification.customHeader, @@ -229,7 +236,7 @@ export class NotificationEntityService implements OnModuleInit { public async pack( src: MiNotification | MiGroupedNotification, meId: MiUser['id'], - // eslint-disable-next-line @typescript-eslint/ban-types + options: { checkValidNotifier?: boolean; }, diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index da96878713..c9939adf11 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -454,12 +454,12 @@ export class UserEntityService implements OnModuleInit { } const followingCount = profile == null ? null : - (profile.followingVisibility === 'public') || isMe ? user.followingCount : + (profile.followingVisibility === 'public') || isMe || iAmModerator ? user.followingCount : (profile.followingVisibility === 'followers') && (relation && relation.isFollowing) ? user.followingCount : null; const followersCount = profile == null ? null : - (profile.followersVisibility === 'public') || isMe ? user.followersCount : + (profile.followersVisibility === 'public') || isMe || iAmModerator ? user.followersCount : (profile.followersVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount : null; @@ -501,11 +501,15 @@ export class UserEntityService implements OnModuleInit { emojis: this.customEmojiService.populateEmojis(user.emojis, user.host), onlineStatus: this.getOnlineStatus(user), // パフォーマンス上の理由でローカルユーザーのみ - badgeRoles: user.host == null ? this.roleService.getUserBadgeRoles(user.id).then(rs => rs.sort((a, b) => b.displayOrder - a.displayOrder).map(r => ({ - name: r.name, - iconUrl: r.iconUrl, - displayOrder: r.displayOrder, - }))) : undefined, + badgeRoles: user.host == null ? this.roleService.getUserBadgeRoles(user.id).then((rs) => rs + .filter((r) => r.isPublic || iAmModerator) + .sort((a, b) => b.displayOrder - a.displayOrder) + .map((r) => ({ + name: r.name, + iconUrl: r.iconUrl, + displayOrder: r.displayOrder, + })), + ) : undefined, ...(isDetailed ? { url: profile!.url, @@ -541,11 +545,6 @@ export class UserEntityService implements OnModuleInit { publicReactions: this.isLocalUser(user) ? profile!.publicReactions : false, // https://github.com/misskey-dev/misskey/issues/12964 followersVisibility: profile!.followersVisibility, followingVisibility: profile!.followingVisibility, - twoFactorEnabled: profile!.twoFactorEnabled, - usePasswordLessLogin: profile!.usePasswordLessLogin, - securityKeys: profile!.twoFactorEnabled - ? this.userSecurityKeysRepository.countBy({ userId: user.id }).then(result => result >= 1) - : false, roles: this.roleService.getUserRoles(user.id).then(roles => roles.filter(role => role.isPublic).sort((a, b) => b.displayOrder - a.displayOrder).map(role => ({ id: role.id, name: role.name, @@ -560,9 +559,18 @@ export class UserEntityService implements OnModuleInit { moderationNote: iAmModerator ? (profile!.moderationNote ?? '') : undefined, } : {}), + ...(isDetailed && (isMe || iAmModerator) ? { + twoFactorEnabled: profile!.twoFactorEnabled, + usePasswordLessLogin: profile!.usePasswordLessLogin, + securityKeys: profile!.twoFactorEnabled + ? this.userSecurityKeysRepository.countBy({ userId: user.id }).then(result => result >= 1) + : false, + } : {}), + ...(isDetailed && isMe ? { avatarId: user.avatarId, bannerId: user.bannerId, + followedMessage: profile!.followedMessage, isModerator: isModerator, isAdmin: isAdmin, injectFeaturedNote: profile!.injectFeaturedNote, @@ -631,6 +639,7 @@ export class UserEntityService implements OnModuleInit { isRenoteMuted: relation.isRenoteMuted, notify: relation.following?.notify ?? 'none', withReplies: relation.following?.withReplies ?? false, + followedMessage: relation.isFollowing ? profile!.followedMessage : undefined, } : {}), } as Promiseable>; diff --git a/packages/backend/src/daemons/ServerStatsService.ts b/packages/backend/src/daemons/ServerStatsService.ts index 2c70344c94..d229efb123 100644 --- a/packages/backend/src/daemons/ServerStatsService.ts +++ b/packages/backend/src/daemons/ServerStatsService.ts @@ -3,13 +3,14 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import si from 'systeminformation'; import Xev from 'xev'; import * as osUtils from 'os-utils'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; import type { OnApplicationShutdown } from '@nestjs/common'; +import { MiMeta } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; const ev = new Xev(); @@ -23,7 +24,8 @@ export class ServerStatsService implements OnApplicationShutdown { private intervalId: NodeJS.Timeout | null = null; constructor( - private metaService: MetaService, + @Inject(DI.meta) + private meta: MiMeta, ) { } @@ -32,7 +34,7 @@ export class ServerStatsService implements OnApplicationShutdown { */ @bindThis public async start(): Promise { - if (!(await this.metaService.fetch(true)).enableServerMachineStats) return; + if (!this.meta.enableServerMachineStats) return; const log = [] as any[]; diff --git a/packages/backend/src/decorators.ts b/packages/backend/src/decorators.ts index 21777657d1..42f925e125 100644 --- a/packages/backend/src/decorators.ts +++ b/packages/backend/src/decorators.ts @@ -10,8 +10,9 @@ * The getter will return a .bind version of the function * and memoize the result against a symbol on the instance */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function bindThis(target: any, key: string, descriptor: any) { - let fn = descriptor.value; + const fn = descriptor.value; if (typeof fn !== 'function') { throw new TypeError(`@bindThis decorator can only be applied to methods not: ${typeof fn}`); @@ -21,26 +22,18 @@ export function bindThis(target: any, key: string, descriptor: any) { configurable: true, get() { // eslint-disable-next-line no-prototype-builtins - if (this === target.prototype || this.hasOwnProperty(key) || - typeof fn !== 'function') { + if (this === target.prototype || this.hasOwnProperty(key)) { return fn; } const boundFn = fn.bind(this); - Object.defineProperty(this, key, { + Reflect.defineProperty(this, key, { + value: boundFn, configurable: true, - get() { - return boundFn; - }, - set(value) { - fn = value; - delete this[key]; - }, + writable: true, }); + return boundFn; }, - set(value: any) { - fn = value; - }, }; } diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 271082b4ff..e599fc7b37 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -6,11 +6,13 @@ export const DI = { config: Symbol('config'), db: Symbol('db'), + meta: Symbol('meta'), meilisearch: Symbol('meilisearch'), redis: Symbol('redis'), redisForPub: Symbol('redisForPub'), redisForSub: Symbol('redisForSub'), redisForTimelines: Symbol('redisForTimelines'), + redisForReactions: Symbol('redisForReactions'), //#region Repositories usersRepository: Symbol('usersRepository'), diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index bba64a06ef..f9692ce5d5 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -7,23 +7,23 @@ import * as Redis from 'ioredis'; import { bindThis } from '@/decorators.js'; export class RedisKVCache { - private redisClient: Redis.Redis; - private name: string; - private lifetime: number; - private memoryCache: MemoryKVCache; - private fetcher: (key: string) => Promise; - private toRedisConverter: (value: T) => string; - private fromRedisConverter: (value: string) => T | undefined; + private readonly lifetime: number; + private readonly memoryCache: MemoryKVCache; + private readonly fetcher: (key: string) => Promise; + private readonly toRedisConverter: (value: T) => string; + private readonly fromRedisConverter: (value: string) => T | undefined; - constructor(redisClient: RedisKVCache['redisClient'], name: RedisKVCache['name'], opts: { - lifetime: RedisKVCache['lifetime']; - memoryCacheLifetime: number; - fetcher: RedisKVCache['fetcher']; - toRedisConverter: RedisKVCache['toRedisConverter']; - fromRedisConverter: RedisKVCache['fromRedisConverter']; - }) { - this.redisClient = redisClient; - this.name = name; + constructor( + private redisClient: Redis.Redis, + private name: string, + opts: { + lifetime: RedisKVCache['lifetime']; + memoryCacheLifetime: number; + fetcher: RedisKVCache['fetcher']; + toRedisConverter: RedisKVCache['toRedisConverter']; + fromRedisConverter: RedisKVCache['fromRedisConverter']; + }, + ) { this.lifetime = opts.lifetime; this.memoryCache = new MemoryKVCache(opts.memoryCacheLifetime); this.fetcher = opts.fetcher; @@ -55,7 +55,13 @@ export class RedisKVCache { const cached = await this.redisClient.get(`kvcache:${this.name}:${key}`); if (cached == null) return undefined; - return this.fromRedisConverter(cached); + + const value = this.fromRedisConverter(cached); + if (value !== undefined) { + this.memoryCache.set(key, value); + } + + return value; } @bindThis @@ -66,6 +72,10 @@ export class RedisKVCache { /** * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します + * This awaits the call to Redis to ensure that the write succeeded, which is important for a few reasons: + * * Other code uses this to synchronize changes between worker processes. A failed write can internally de-sync the cluster. + * * Without an `await`, consecutive calls could race. An unlucky race could result in the older write overwriting the newer value. + * * Not awaiting here makes the entire cache non-consistent. The prevents many possible uses. */ @bindThis public async fetch(key: string): Promise { @@ -77,14 +87,14 @@ export class RedisKVCache { // Cache MISS const value = await this.fetcher(key); - this.set(key, value); + await this.set(key, value); return value; } @bindThis public async refresh(key: string) { const value = await this.fetcher(key); - this.set(key, value); + await this.set(key, value); // TODO: イベント発行して他プロセスのメモリキャッシュも更新できるようにする } @@ -101,23 +111,23 @@ export class RedisKVCache { } export class RedisSingleCache { - private redisClient: Redis.Redis; - private name: string; - private lifetime: number; - private memoryCache: MemorySingleCache; - private fetcher: () => Promise; - private toRedisConverter: (value: T) => string; - private fromRedisConverter: (value: string) => T | undefined; + private readonly lifetime: number; + private readonly memoryCache: MemorySingleCache; + private readonly fetcher: () => Promise; + private readonly toRedisConverter: (value: T) => string; + private readonly fromRedisConverter: (value: string) => T | undefined; - constructor(redisClient: RedisSingleCache['redisClient'], name: RedisSingleCache['name'], opts: { - lifetime: RedisSingleCache['lifetime']; - memoryCacheLifetime: number; - fetcher: RedisSingleCache['fetcher']; - toRedisConverter: RedisSingleCache['toRedisConverter']; - fromRedisConverter: RedisSingleCache['fromRedisConverter']; - }) { - this.redisClient = redisClient; - this.name = name; + constructor( + private redisClient: Redis.Redis, + private name: string, + opts: { + lifetime: number; + memoryCacheLifetime: number; + fetcher: RedisSingleCache['fetcher']; + toRedisConverter: RedisSingleCache['toRedisConverter']; + fromRedisConverter: RedisSingleCache['fromRedisConverter']; + }, + ) { this.lifetime = opts.lifetime; this.memoryCache = new MemorySingleCache(opts.memoryCacheLifetime); this.fetcher = opts.fetcher; @@ -149,7 +159,13 @@ export class RedisSingleCache { const cached = await this.redisClient.get(`singlecache:${this.name}`); if (cached == null) return undefined; - return this.fromRedisConverter(cached); + + const value = this.fromRedisConverter(cached); + if (value !== undefined) { + this.memoryCache.set(value); + } + + return value; } @bindThis @@ -160,6 +176,10 @@ export class RedisSingleCache { /** * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します + * This awaits the call to Redis to ensure that the write succeeded, which is important for a few reasons: + * * Other code uses this to synchronize changes between worker processes. A failed write can internally de-sync the cluster. + * * Without an `await`, consecutive calls could race. An unlucky race could result in the older write overwriting the newer value. + * * Not awaiting here makes the entire cache non-consistent. The prevents many possible uses. */ @bindThis public async fetch(): Promise { @@ -171,14 +191,14 @@ export class RedisSingleCache { // Cache MISS const value = await this.fetcher(); - this.set(value); + await this.set(value); return value; } @bindThis public async refresh() { const value = await this.fetcher(); - this.set(value); + await this.set(value); // TODO: イベント発行して他プロセスのメモリキャッシュも更新できるようにする } @@ -187,22 +207,12 @@ export class RedisSingleCache { // TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする? export class MemoryKVCache { - /** - * データを持つマップ - * @deprecated これを直接操作するべきではない - */ - public cache: Map; - private lifetime: number; - private gcIntervalHandle: NodeJS.Timeout; + private readonly cache = new Map(); + private readonly gcIntervalHandle = setInterval(() => this.gc(), 1000 * 60 * 3); // 3m - constructor(lifetime: MemoryKVCache['lifetime']) { - this.cache = new Map(); - this.lifetime = lifetime; - - this.gcIntervalHandle = setInterval(() => { - this.gc(); - }, 1000 * 60 * 3); - } + constructor( + private readonly lifetime: number, + ) {} @bindThis /** @@ -287,10 +297,14 @@ export class MemoryKVCache { @bindThis public gc(): void { const now = Date.now(); + for (const [key, { date }] of this.cache.entries()) { - if ((now - date) > this.lifetime) { - this.cache.delete(key); - } + // The map is ordered from oldest to youngest. + // We can stop once we find an entry that's still active, because all following entries must *also* be active. + const age = now - date; + if (age < this.lifetime) break; + + this.cache.delete(key); } } @@ -298,16 +312,19 @@ export class MemoryKVCache { public dispose(): void { clearInterval(this.gcIntervalHandle); } + + public get entries() { + return this.cache.entries(); + } } export class MemorySingleCache { private cachedAt: number | null = null; private value: T | undefined; - private lifetime: number; - constructor(lifetime: MemorySingleCache['lifetime']) { - this.lifetime = lifetime; - } + constructor( + private lifetime: number, + ) {} @bindThis public set(value: T): void { diff --git a/packages/backend/src/misc/collapsed-queue.ts b/packages/backend/src/misc/collapsed-queue.ts new file mode 100644 index 0000000000..5bc20a78ae --- /dev/null +++ b/packages/backend/src/misc/collapsed-queue.ts @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +type Job = { + value: V; + timer: NodeJS.Timeout; +}; + +// TODO: redis使えるようにする +export class CollapsedQueue { + private jobs: Map> = new Map(); + + constructor( + private timeout: number, + private collapse: (oldValue: V, newValue: V) => V, + private perform: (key: K, value: V) => Promise, + ) {} + + enqueue(key: K, value: V) { + if (this.jobs.has(key)) { + const old = this.jobs.get(key)!; + const merged = this.collapse(old.value, value); + this.jobs.set(key, { ...old, value: merged }); + } else { + const timer = setTimeout(() => { + const job = this.jobs.get(key)!; + this.jobs.delete(key); + this.perform(key, job.value); + }, this.timeout); + this.jobs.set(key, { value, timer }); + } + } + + async performAllNow() { + const entries = [...this.jobs.entries()]; + this.jobs.clear(); + for (const [_key, job] of entries) { + clearTimeout(job.timer); + } + await Promise.allSettled(entries.map(([key, job]) => this.perform(key, job.value))); + } +} diff --git a/packages/backend/src/misc/fastify-hook-handlers.ts b/packages/backend/src/misc/fastify-hook-handlers.ts index 3e1c099e00..fa3ef0a267 100644 --- a/packages/backend/src/misc/fastify-hook-handlers.ts +++ b/packages/backend/src/misc/fastify-hook-handlers.ts @@ -8,7 +8,7 @@ import type { onRequestHookHandler } from 'fastify'; export const handleRequestRedirectToOmitSearch: onRequestHookHandler = (request, reply, done) => { const index = request.url.indexOf('?'); if (~index) { - reply.redirect(301, request.url.slice(0, index)); + reply.redirect(request.url.slice(0, index), 301); } done(); }; diff --git a/packages/backend/src/misc/is-user-related.ts b/packages/backend/src/misc/is-user-related.ts index 93c9b2b814..862d6e6a38 100644 --- a/packages/backend/src/misc/is-user-related.ts +++ b/packages/backend/src/misc/is-user-related.ts @@ -4,6 +4,10 @@ */ export function isUserRelated(note: any, userIds: Set, ignoreAuthor = false): boolean { + if (!note) { + return false; + } + if (userIds.has(note.userId) && !ignoreAuthor) { return true; } diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index a721b8663c..040e36228c 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -144,7 +144,9 @@ export interface Schema extends OfSchema { readonly type?: TypeStringef; readonly nullable?: boolean; readonly optional?: boolean; + readonly prefixItems?: ReadonlyArray; readonly items?: Schema; + readonly unevaluatedItems?: Schema | boolean; readonly properties?: Obj; readonly required?: ReadonlyArray, string>>; readonly description?: string; @@ -198,6 +200,7 @@ type UnionSchemaType = X //type UnionObjectSchemaType = X extends any ? ObjectSchemaType : never; type UnionObjType = a[number]> = X extends any ? ObjType : never; type ArrayUnion = T extends any ? Array : never; +type ArrayToTuple> = { [K in keyof X]: SchemaType }; type ObjectSchemaTypeDef

= p['ref'] extends keyof typeof refs ? Packed : @@ -232,6 +235,12 @@ export type SchemaTypeDef

= p['items']['allOf'] extends ReadonlyArray ? UnionToIntersection>>[] : never ) : + p['prefixItems'] extends ReadonlyArray ? ( + p['items'] extends NonNullable ? [...ArrayToTuple, ...SchemaType[]] : + p['items'] extends false ? ArrayToTuple : + p['unevaluatedItems'] extends false ? ArrayToTuple : + [...ArrayToTuple, ...unknown[]] + ) : p['items'] extends NonNullable ? SchemaType[] : any[] ) : diff --git a/packages/backend/src/misc/json-value.ts b/packages/backend/src/misc/json-value.ts new file mode 100644 index 0000000000..bd7fe12058 --- /dev/null +++ b/packages/backend/src/misc/json-value.ts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export type JsonValue = JsonArray | JsonObject | string | number | boolean | null; +export type JsonObject = {[K in string]?: JsonValue}; +export type JsonArray = JsonValue[]; + +export function isJsonObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} diff --git a/packages/backend/src/models/AbuseUserReport.ts b/packages/backend/src/models/AbuseUserReport.ts index 0615fd7eb5..cb5672e4ac 100644 --- a/packages/backend/src/models/AbuseUserReport.ts +++ b/packages/backend/src/models/AbuseUserReport.ts @@ -50,6 +50,9 @@ export class MiAbuseUserReport { }) public resolved: boolean; + /** + * リモートサーバーに転送したかどうか + */ @Column('boolean', { default: false, }) @@ -60,6 +63,21 @@ export class MiAbuseUserReport { }) public comment: string; + @Column('varchar', { + length: 8192, default: '', + }) + public moderationNote: string; + + /** + * accept 是認 ... 通報内容が正当であり、肯定的に対応された + * reject 否認 ... 通報内容が正当でなく、否定的に対応された + * null ... その他 + */ + @Column('varchar', { + length: 128, nullable: true, + }) + public resolvedAs: 'accept' | 'reject' | null; + //#region Denormalized fields @Index() @Column('varchar', { diff --git a/packages/backend/src/models/DriveFile.ts b/packages/backend/src/models/DriveFile.ts index 438b32f79a..7b03e3e494 100644 --- a/packages/backend/src/models/DriveFile.ts +++ b/packages/backend/src/models/DriveFile.ts @@ -82,7 +82,7 @@ export class MiDriveFile { public storedInternal: boolean; @Column('varchar', { - length: 512, + length: 1024, comment: 'The URL of the DriveFile.', }) public url: string; @@ -124,13 +124,13 @@ export class MiDriveFile { @Index() @Column('varchar', { - length: 512, nullable: true, + length: 1024, nullable: true, comment: 'The URI of the DriveFile. it will be null when the DriveFile is local.', }) public uri: string | null; @Column('varchar', { - length: 512, nullable: true, + length: 1024, nullable: true, }) public src: string | null; diff --git a/packages/backend/src/models/Flash.ts b/packages/backend/src/models/Flash.ts index a1469a0d94..5db7dca992 100644 --- a/packages/backend/src/models/Flash.ts +++ b/packages/backend/src/models/Flash.ts @@ -7,6 +7,9 @@ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typ import { id } from './util/id.js'; import { MiUser } from './User.js'; +export const flashVisibility = ['public', 'private'] as const; +export type FlashVisibility = typeof flashVisibility[number]; + @Entity('flash') export class MiFlash { @PrimaryColumn(id()) @@ -63,5 +66,5 @@ export class MiFlash { @Column('varchar', { length: 512, default: 'public', }) - public visibility: 'public' | 'private'; + public visibility: FlashVisibility; } diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index ad306fcad6..fd007de6c6 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -86,6 +86,11 @@ export class MiMeta { }) public silencedHosts: string[]; + @Column('varchar', { + length: 1024, array: true, default: '{}', + }) + public mediaSilencedHosts: string[]; + @Column('varchar', { length: 1024, nullable: true, @@ -253,6 +258,11 @@ export class MiMeta { }) public turnstileSecretKey: string | null; + @Column('boolean', { + default: false, + }) + public enableTestcaptcha: boolean; + // chaptcha系を追加した際にはnodeinfoのレスポンスに追加するのを忘れないようにすること @Column('enum', { @@ -584,6 +594,11 @@ export class MiMeta { }) public perUserListTimelineCacheMax: number; + @Column('boolean', { + default: false, + }) + public enableReactionsBuffering: boolean; + @Column('integer', { default: 0, }) @@ -620,4 +635,17 @@ export class MiMeta { nullable: true, }) public urlPreviewUserAgent: string | null; + + @Column('varchar', { + length: 128, + default: 'all', + }) + public federation: 'all' | 'specified' | 'none'; + + @Column('varchar', { + length: 1024, + array: true, + default: '{}', + }) + public federationHosts: string[]; } diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index df88b99636..b7f8e94d69 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -3,10 +3,12 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { userExportableEntities } from '@/types.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; import { MiAccessToken } from './AccessToken.js'; import { MiRole } from './Role.js'; +import { MiDriveFile } from './DriveFile.js'; export type MiNotification = { type: 'note'; @@ -67,6 +69,7 @@ export type MiNotification = { id: string; createdAt: string; notifierId: MiUser['id']; + message: string | null; } | { type: 'roleAssigned'; id: string; @@ -77,6 +80,16 @@ export type MiNotification = { id: string; createdAt: string; achievement: string; +} | { + type: 'exportCompleted'; + id: string; + createdAt: string; + exportedEntity: typeof userExportableEntities[number]; + fileId: MiDriveFile['id']; +} | { + type: 'login'; + id: string; + createdAt: string; } | { type: 'app'; id: string; @@ -85,7 +98,7 @@ export type MiNotification = { /** * アプリ通知のbody */ - customBody: string | null; + customBody: string; /** * アプリ通知のheader diff --git a/packages/backend/src/models/SystemWebhook.ts b/packages/backend/src/models/SystemWebhook.ts index 86fb323d1d..d6c27eae51 100644 --- a/packages/backend/src/models/SystemWebhook.ts +++ b/packages/backend/src/models/SystemWebhook.ts @@ -12,6 +12,8 @@ export const systemWebhookEventTypes = [ 'abuseReport', // 通報を処理したとき 'abuseReportResolved', + // ユーザが作成された時 + 'userCreated', ] as const; export type SystemWebhookEventType = typeof systemWebhookEventTypes[number]; diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index 9e2d7a3444..805a1e75ae 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -155,6 +155,11 @@ export class MiUser { }) public tags: string[]; + @Column('integer', { + default: 0, + }) + public score: number; + @Column('boolean', { default: false, comment: 'Whether the User is suspended.', @@ -289,5 +294,6 @@ export const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toStr export const passwordSchema = { type: 'string', minLength: 1 } as const; export const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; export const descriptionSchema = { type: 'string', minLength: 1, maxLength: 1500 } as const; +export const followedMessageSchema = { type: 'string', minLength: 1, maxLength: 256 } as const; export const locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; export const birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts index 7dbe0b3717..5544555296 100644 --- a/packages/backend/src/models/UserProfile.ts +++ b/packages/backend/src/models/UserProfile.ts @@ -42,6 +42,14 @@ export class MiUserProfile { }) public description: string | null; + // フォローされた際のメッセージ + @Column('varchar', { + length: 256, nullable: true, + }) + public followedMessage: string | null; + + // TODO: 鍵アカウントの場合の、フォローリクエスト受信時のメッセージも設定できるようにする + @Column('jsonb', { default: [], }) diff --git a/packages/backend/src/models/Webhook.ts b/packages/backend/src/models/Webhook.ts index db24c03b3d..b4cab4edc8 100644 --- a/packages/backend/src/models/Webhook.ts +++ b/packages/backend/src/models/Webhook.ts @@ -8,6 +8,7 @@ import { id } from './util/id.js'; import { MiUser } from './User.js'; export const webhookEventTypes = ['mention', 'unfollow', 'follow', 'followed', 'note', 'reply', 'renote', 'reaction'] as const; +export type WebhookEventTypes = typeof webhookEventTypes[number]; @Entity('webhook') export class MiWebhook { diff --git a/packages/backend/src/models/json-schema/drive-file.ts b/packages/backend/src/models/json-schema/drive-file.ts index ca88cc0e39..5ee1561c50 100644 --- a/packages/backend/src/models/json-schema/drive-file.ts +++ b/packages/backend/src/models/json-schema/drive-file.ts @@ -20,7 +20,7 @@ export const packedDriveFileSchema = { name: { type: 'string', optional: false, nullable: false, - example: 'lenna.jpg', + example: '192.jpg', }, type: { type: 'string', diff --git a/packages/backend/src/models/json-schema/federation-instance.ts b/packages/backend/src/models/json-schema/federation-instance.ts index ed40d405c6..912a0399d8 100644 --- a/packages/backend/src/models/json-schema/federation-instance.ts +++ b/packages/backend/src/models/json-schema/federation-instance.ts @@ -88,6 +88,10 @@ export const packedFederationInstanceSchema = { type: 'boolean', optional: false, nullable: false, }, + isMediaSilenced: { + type: 'boolean', + optional: false, nullable: false, + }, iconUrl: { type: 'string', optional: false, nullable: true, diff --git a/packages/backend/src/models/json-schema/flash.ts b/packages/backend/src/models/json-schema/flash.ts index 952df649ad..42b2172409 100644 --- a/packages/backend/src/models/json-schema/flash.ts +++ b/packages/backend/src/models/json-schema/flash.ts @@ -44,6 +44,11 @@ export const packedFlashSchema = { type: 'string', optional: false, nullable: false, }, + visibility: { + type: 'string', + optional: false, nullable: false, + enum: ['private', 'public'], + }, likedCount: { type: 'number', optional: false, nullable: true, diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts index e7bc6356e5..e3fd63464a 100644 --- a/packages/backend/src/models/json-schema/meta.ts +++ b/packages/backend/src/models/json-schema/meta.ts @@ -115,6 +115,10 @@ export const packedMetaLiteSchema = { type: 'string', optional: false, nullable: true, }, + enableTestcaptcha: { + type: 'boolean', + optional: false, nullable: false, + }, swPublickey: { type: 'string', optional: false, nullable: true, @@ -247,6 +251,16 @@ export const packedMetaLiteSchema = { optional: false, nullable: false, ref: 'RolePolicies', }, + noteSearchableScope: { + type: 'string', + enum: ['local', 'global'], + optional: false, nullable: false, + default: 'local', + }, + maxFileSize: { + type: 'number', + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/backend/src/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts index 2641161c8b..432c096e48 100644 --- a/packages/backend/src/models/json-schema/note.ts +++ b/packages/backend/src/models/json-schema/note.ts @@ -204,6 +204,7 @@ export const packedNoteSchema = { reactionAcceptance: { type: 'string', optional: false, nullable: true, + enum: ['likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote', null], }, reactionEmojis: { type: 'object', diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index b4c4442758..cddaf4bc83 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -3,7 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { notificationTypes } from '@/types.js'; +import { ACHIEVEMENT_TYPES } from '@/core/AchievementService.js'; +import { notificationTypes, userExportableEntities } from '@/types.js'; const baseSchema = { type: 'object', @@ -266,6 +267,10 @@ export const packedNotificationSchema = { optional: false, nullable: false, format: 'id', }, + message: { + type: 'string', + optional: false, nullable: true, + }, }, }, { type: 'object', @@ -294,6 +299,37 @@ export const packedNotificationSchema = { achievement: { type: 'string', optional: false, nullable: false, + enum: ACHIEVEMENT_TYPES, + }, + }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, + enum: ['exportCompleted'], + }, + exportedEntity: { + type: 'string', + optional: false, nullable: false, + enum: userExportableEntities, + }, + fileId: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, + enum: ['login'], }, }, }, { @@ -311,11 +347,11 @@ export const packedNotificationSchema = { }, header: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, icon: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, }, }, { diff --git a/packages/backend/src/models/json-schema/role.ts b/packages/backend/src/models/json-schema/role.ts index d9987a70c3..3537de94c8 100644 --- a/packages/backend/src/models/json-schema/role.ts +++ b/packages/backend/src/models/json-schema/role.ts @@ -228,6 +228,10 @@ export const packedRolePoliciesSchema = { type: 'boolean', optional: false, nullable: false, }, + canUpdateBioMedia: { + type: 'boolean', + optional: false, nullable: false, + }, pinLimit: { type: 'integer', optional: false, nullable: false, @@ -268,6 +272,26 @@ export const packedRolePoliciesSchema = { type: 'integer', optional: false, nullable: false, }, + canImportAntennas: { + type: 'boolean', + optional: false, nullable: false, + }, + canImportBlocking: { + type: 'boolean', + optional: false, nullable: false, + }, + canImportFollowing: { + type: 'boolean', + optional: false, nullable: false, + }, + canImportMuting: { + type: 'boolean', + optional: false, nullable: false, + }, + canImportUserLists: { + type: 'boolean', + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 947a9317d7..9cffd680f2 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -346,21 +346,6 @@ export const packedUserDetailedNotMeOnlySchema = { nullable: false, optional: false, enum: ['public', 'followers', 'private'], }, - twoFactorEnabled: { - type: 'boolean', - nullable: false, optional: false, - default: false, - }, - usePasswordLessLogin: { - type: 'boolean', - nullable: false, optional: false, - default: false, - }, - securityKeys: { - type: 'boolean', - nullable: false, optional: false, - default: false, - }, roles: { type: 'array', nullable: false, optional: false, @@ -370,6 +355,10 @@ export const packedUserDetailedNotMeOnlySchema = { ref: 'RoleLite', }, }, + followedMessage: { + type: 'string', + nullable: true, optional: true, + }, memo: { type: 'string', nullable: true, optional: false, @@ -378,6 +367,18 @@ export const packedUserDetailedNotMeOnlySchema = { type: 'string', nullable: false, optional: true, }, + twoFactorEnabled: { + type: 'boolean', + nullable: false, optional: true, + }, + usePasswordLessLogin: { + type: 'boolean', + nullable: false, optional: true, + }, + securityKeys: { + type: 'boolean', + nullable: false, optional: true, + }, //#region relations isFollowing: { type: 'boolean', @@ -437,6 +438,10 @@ export const packedMeDetailedOnlySchema = { nullable: true, optional: false, format: 'id', }, + followedMessage: { + type: 'string', + nullable: true, optional: false, + }, isModerator: { type: 'boolean', nullable: true, optional: false, @@ -622,6 +627,21 @@ export const packedMeDetailedOnlySchema = { nullable: false, optional: false, ref: 'RolePolicies', }, + twoFactorEnabled: { + type: 'boolean', + nullable: false, optional: false, + default: false, + }, + usePasswordLessLogin: { + type: 'boolean', + nullable: false, optional: false, + default: false, + }, + securityKeys: { + type: 'boolean', + nullable: false, optional: false, + default: false, + }, //#region secrets email: { type: 'string', diff --git a/packages/backend/src/queue/QueueProcessorModule.ts b/packages/backend/src/queue/QueueProcessorModule.ts index a1fd38fcc5..9044285bf6 100644 --- a/packages/backend/src/queue/QueueProcessorModule.ts +++ b/packages/backend/src/queue/QueueProcessorModule.ts @@ -6,6 +6,7 @@ import { Module } from '@nestjs/common'; import { CoreModule } from '@/core/CoreModule.js'; import { GlobalModule } from '@/GlobalModule.js'; +import { CheckModeratorsActivityProcessorService } from '@/queue/processors/CheckModeratorsActivityProcessorService.js'; import { QueueLoggerService } from './QueueLoggerService.js'; import { QueueProcessorService } from './QueueProcessorService.js'; import { DeliverProcessorService } from './processors/DeliverProcessorService.js'; @@ -14,6 +15,7 @@ import { InboxProcessorService } from './processors/InboxProcessorService.js'; import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; import { CheckExpiredMutingsProcessorService } from './processors/CheckExpiredMutingsProcessorService.js'; +import { BakeBufferedReactionsProcessorService } from './processors/BakeBufferedReactionsProcessorService.js'; import { CleanChartsProcessorService } from './processors/CleanChartsProcessorService.js'; import { CleanProcessorService } from './processors/CleanProcessorService.js'; import { CleanRemoteFilesProcessorService } from './processors/CleanRemoteFilesProcessorService.js'; @@ -51,6 +53,7 @@ import { RelationshipProcessorService } from './processors/RelationshipProcessor ResyncChartsProcessorService, CleanChartsProcessorService, CheckExpiredMutingsProcessorService, + BakeBufferedReactionsProcessorService, CleanProcessorService, DeleteDriveFilesProcessorService, ExportCustomEmojisProcessorService, @@ -78,6 +81,8 @@ import { RelationshipProcessorService } from './processors/RelationshipProcessor DeliverProcessorService, InboxProcessorService, AggregateRetentionProcessorService, + CheckExpiredMutingsProcessorService, + CheckModeratorsActivityProcessorService, QueueProcessorService, ], exports: [ diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 7bd74f3210..6940e1c188 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -10,6 +10,7 @@ import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; +import { CheckModeratorsActivityProcessorService } from '@/queue/processors/CheckModeratorsActivityProcessorService.js'; import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js'; @@ -39,6 +40,7 @@ import { TickChartsProcessorService } from './processors/TickChartsProcessorServ import { ResyncChartsProcessorService } from './processors/ResyncChartsProcessorService.js'; import { CleanChartsProcessorService } from './processors/CleanChartsProcessorService.js'; import { CheckExpiredMutingsProcessorService } from './processors/CheckExpiredMutingsProcessorService.js'; +import { BakeBufferedReactionsProcessorService } from './processors/BakeBufferedReactionsProcessorService.js'; import { CleanProcessorService } from './processors/CleanProcessorService.js'; import { AggregateRetentionProcessorService } from './processors/AggregateRetentionProcessorService.js'; import { QueueLoggerService } from './QueueLoggerService.js'; @@ -65,7 +67,7 @@ function getJobInfo(job: Bull.Job | undefined, increment = false): string { // onActiveとかonCompletedのattemptsMadeがなぜか0始まりなのでインクリメントする const currentAttempts = job.attemptsMade + (increment ? 1 : 0); - const maxAttempts = job.opts ? job.opts.attempts : 0; + const maxAttempts = job.opts.attempts ?? 0; return `id=${job.id} attempts=${currentAttempts}/${maxAttempts} age=${formated}`; } @@ -118,24 +120,36 @@ export class QueueProcessorService implements OnApplicationShutdown { private cleanChartsProcessorService: CleanChartsProcessorService, private aggregateRetentionProcessorService: AggregateRetentionProcessorService, private checkExpiredMutingsProcessorService: CheckExpiredMutingsProcessorService, + private bakeBufferedReactionsProcessorService: BakeBufferedReactionsProcessorService, + private checkModeratorsActivityProcessorService: CheckModeratorsActivityProcessorService, private cleanProcessorService: CleanProcessorService, ) { this.logger = this.queueLoggerService.logger; - function renderError(e: Error): any { - if (e) { // 何故かeがundefinedで来ることがある - return { - stack: e.stack, - message: e.message, - name: e.name, - }; - } else { - return { - stack: '?', - message: '?', - name: '?', - }; + function renderError(e?: Error) { + // 何故かeがundefinedで来ることがある + if (!e) return '?'; + + if (e instanceof Bull.UnrecoverableError || e.name === 'AbortError') { + return `${e.name}: ${e.message}`; } + + return { + stack: e.stack, + message: e.message, + name: e.name, + }; + } + + function renderJob(job?: Bull.Job) { + if (!job) return '?'; + + return { + name: job.name || undefined, + info: getJobInfo(job), + failedReason: job.failedReason || undefined, + data: job.data, + }; } //#region system @@ -147,6 +161,8 @@ export class QueueProcessorService implements OnApplicationShutdown { case 'cleanCharts': return this.cleanChartsProcessorService.process(); case 'aggregateRetention': return this.aggregateRetentionProcessorService.process(); case 'checkExpiredMutings': return this.checkExpiredMutingsProcessorService.process(); + case 'bakeBufferedReactions': return this.bakeBufferedReactionsProcessorService.process(); + case 'checkModeratorsActivity': return this.checkModeratorsActivityProcessorService.process(); case 'clean': return this.cleanProcessorService.process(); default: throw new Error(`unrecognized job type ${job.name} for system`); } @@ -169,15 +185,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active id=${job.id}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err: Error) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.name}: ${err.message}) id=${job?.id ?? '?'}`, { job: renderJob(job), e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.message}`, { + Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -226,15 +242,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active id=${job.id}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.name}: ${err.message}) id=${job?.id ?? '?'}`, { job: renderJob(job), e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.message}`, { + Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -266,15 +282,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + logger.error(`failed(${err.name}: ${err.message}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: Deliver: ${err.message}`, { + Sentry.captureMessage(`Queue: Deliver: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -306,15 +322,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.name}: ${err.message}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job: renderJob(job), e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: Inbox: ${err.message}`, { + Sentry.captureMessage(`Queue: Inbox: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -346,15 +362,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + logger.error(`failed(${err.name}: ${err.message}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: UserWebhookDeliver: ${err.message}`, { + Sentry.captureMessage(`Queue: UserWebhookDeliver: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -386,15 +402,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + logger.error(`failed(${err.name}: ${err.message}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: SystemWebhookDeliver: ${err.message}`, { + Sentry.captureMessage(`Queue: SystemWebhookDeliver: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -433,15 +449,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active id=${job.id}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.name}: ${err.message}) id=${job?.id ?? '?'}`, { job: renderJob(job), e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.message}`, { + Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -474,15 +490,15 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('active', (job) => logger.debug(`active id=${job.id}`)) .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.name}: ${err.message}) id=${job?.id ?? '?'}`, { job: renderJob(job), e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.message}`, { + Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.name}: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('error', (err: Error) => logger.error(`error ${err.name}: ${err.message}`, { e: renderError(err) })) .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion diff --git a/packages/backend/src/queue/processors/BakeBufferedReactionsProcessorService.ts b/packages/backend/src/queue/processors/BakeBufferedReactionsProcessorService.ts new file mode 100644 index 0000000000..d49c99f694 --- /dev/null +++ b/packages/backend/src/queue/processors/BakeBufferedReactionsProcessorService.ts @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import type Logger from '@/logger.js'; +import { bindThis } from '@/decorators.js'; +import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; +import { QueueLoggerService } from '../QueueLoggerService.js'; +import type * as Bull from 'bullmq'; +import { MiMeta } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; + +@Injectable() +export class BakeBufferedReactionsProcessorService { + private logger: Logger; + + constructor( + @Inject(DI.meta) + private meta: MiMeta, + + private reactionsBufferingService: ReactionsBufferingService, + private queueLoggerService: QueueLoggerService, + ) { + this.logger = this.queueLoggerService.logger.createSubLogger('bake-buffered-reactions'); + } + + @bindThis + public async process(): Promise { + if (!this.meta.enableReactionsBuffering) { + this.logger.info('Reactions buffering is disabled. Skipping...'); + return; + } + + this.logger.info('Baking buffered reactions...'); + + await this.reactionsBufferingService.bake(); + + this.logger.succ('All buffered reactions baked.'); + } +} diff --git a/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts b/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts new file mode 100644 index 0000000000..f2677f8e5c --- /dev/null +++ b/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts @@ -0,0 +1,127 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import type Logger from '@/logger.js'; +import { bindThis } from '@/decorators.js'; +import { MetaService } from '@/core/MetaService.js'; +import { RoleService } from '@/core/RoleService.js'; +import { QueueLoggerService } from '../QueueLoggerService.js'; + +// モデレーターが不在と判断する日付の閾値 +const MODERATOR_INACTIVITY_LIMIT_DAYS = 7; +const ONE_DAY_MILLI_SEC = 1000 * 60 * 60 * 24; + +@Injectable() +export class CheckModeratorsActivityProcessorService { + private logger: Logger; + + constructor( + private metaService: MetaService, + private roleService: RoleService, + private queueLoggerService: QueueLoggerService, + ) { + this.logger = this.queueLoggerService.logger.createSubLogger('check-moderators-activity'); + } + + @bindThis + public async process(): Promise { + this.logger.info('start.'); + + const meta = await this.metaService.fetch(false); + if (!meta.disableRegistration) { + await this.processImpl(); + } else { + this.logger.info('is already invitation only.'); + } + + this.logger.succ('finish.'); + } + + @bindThis + private async processImpl() { + const { isModeratorsInactive, inactivityLimitCountdown } = await this.evaluateModeratorsInactiveDays(); + if (isModeratorsInactive) { + this.logger.warn(`The moderator has been inactive for ${MODERATOR_INACTIVITY_LIMIT_DAYS} days. We will move to invitation only.`); + await this.changeToInvitationOnly(); + + // TODO: モデレータに通知メール+Misskey通知 + // TODO: SystemWebhook通知 + } else { + if (inactivityLimitCountdown <= 2) { + this.logger.warn(`A moderator has been inactive for a period of time. If you are inactive for an additional ${inactivityLimitCountdown} days, it will switch to invitation only.`); + + // TODO: 警告メール + } + } + } + + /** + * モデレーターが不在であるかどうかを確認する。trueの場合はモデレーターが不在である。 + * isModerator, isAdministrator, isRootのいずれかがtrueのユーザを対象に、 + * {@link MiUser.lastActiveDate}の値が実行日時の{@link MODERATOR_INACTIVITY_LIMIT_DAYS}日前よりも古いユーザがいるかどうかを確認する。 + * {@link MiUser.lastActiveDate}がnullの場合は、そのユーザは確認の対象外とする。 + * + * ----- + * + * ### サンプルパターン + * - 実行日時: 2022-01-30 12:00:00 + * - 判定基準: 2022-01-23 12:00:00(実行日時の{@link MODERATOR_INACTIVITY_LIMIT_DAYS}日前) + * + * #### パターン① + * - モデレータA: lastActiveDate = 2022-01-20 00:00:00 ※アウト + * - モデレータB: lastActiveDate = 2022-01-23 12:00:00 ※セーフ(判定基準と同値なのでギリギリ残り0日) + * - モデレータC: lastActiveDate = 2022-01-23 11:59:59 ※アウト(残り-1日) + * - モデレータD: lastActiveDate = null + * + * この場合、モデレータBのアクティビティのみ判定基準日よりも古くないため、モデレーターが在席と判断される。 + * + * #### パターン② + * - モデレータA: lastActiveDate = 2022-01-20 00:00:00 ※アウト + * - モデレータB: lastActiveDate = 2022-01-22 12:00:00 ※アウト(残り-1日) + * - モデレータC: lastActiveDate = 2022-01-23 11:59:59 ※アウト(残り-1日) + * - モデレータD: lastActiveDate = null + * + * この場合、モデレータA, B, Cのアクティビティは判定基準日よりも古いため、モデレーターが不在と判断される。 + */ + @bindThis + public async evaluateModeratorsInactiveDays() { + const today = new Date(); + const inactivePeriod = new Date(today); + inactivePeriod.setDate(today.getDate() - MODERATOR_INACTIVITY_LIMIT_DAYS); + + const moderators = await this.fetchModerators() + .then(it => it.filter(it => it.lastActiveDate != null)); + const inactiveModerators = moderators + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .filter(it => it.lastActiveDate!.getTime() < inactivePeriod.getTime()); + + // 残りの猶予を示したいので、最終アクティブ日時が一番若いモデレータの日数を基準に猶予を計算する + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const newestLastActiveDate = new Date(Math.max(...moderators.map(it => it.lastActiveDate!.getTime()))); + const inactivityLimitCountdown = Math.floor((newestLastActiveDate.getTime() - inactivePeriod.getTime()) / ONE_DAY_MILLI_SEC); + + return { + isModeratorsInactive: inactiveModerators.length === moderators.length, + inactiveModerators, + inactivityLimitCountdown, + }; + } + + @bindThis + private async changeToInvitationOnly() { + await this.metaService.update({ disableRegistration: true }); + } + + @bindThis + private async fetchModerators() { + // TODO: モデレーター以外にも特別な権限を持つユーザーがいる場合は考慮する + return this.roleService.getModerators({ + includeAdmins: true, + includeRoot: true, + excludeExpire: true, + }); + } +} diff --git a/packages/backend/src/queue/processors/DeliverProcessorService.ts b/packages/backend/src/queue/processors/DeliverProcessorService.ts index d665945861..9590a4fe71 100644 --- a/packages/backend/src/queue/processors/DeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/DeliverProcessorService.ts @@ -7,9 +7,8 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Bull from 'bullmq'; import { Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { InstancesRepository } from '@/models/_.js'; +import type { InstancesRepository, MiMeta } from '@/models/_.js'; import type Logger from '@/logger.js'; -import { MetaService } from '@/core/MetaService.js'; import { ApRequestService } from '@/core/activitypub/ApRequestService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js'; @@ -31,10 +30,12 @@ export class DeliverProcessorService { private latest: string | null; constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.instancesRepository) private instancesRepository: InstancesRepository, - private metaService: MetaService, private utilityService: UtilityService, private federatedInstanceService: FederatedInstanceService, private fetchInstanceMetadataService: FetchInstanceMetadataService, @@ -45,16 +46,14 @@ export class DeliverProcessorService { private queueLoggerService: QueueLoggerService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('deliver'); - this.suspendedHostsCache = new MemorySingleCache(1000 * 60 * 60); + this.suspendedHostsCache = new MemorySingleCache(1000 * 60 * 60); // 1h } @bindThis public async process(job: Bull.Job): Promise { const { host } = new URL(job.data.to); - // ブロックしてたら中断 - const meta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(meta.blockedHosts, this.utilityService.toPuny(host))) { + if (!this.utilityService.isFederationAllowedUri(job.data.to)) { return 'skip (blocked)'; } @@ -88,7 +87,7 @@ export class DeliverProcessorService { this.apRequestChart.deliverSucc(); this.federationChart.deliverd(i.host, true); - if (meta.enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.requestSent(i.host, true); } }); @@ -120,7 +119,7 @@ export class DeliverProcessorService { this.apRequestChart.deliverFail(); this.federationChart.deliverd(i.host, false); - if (meta.enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.requestSent(i.host, false); } }); diff --git a/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts b/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts index 29c1f27bb1..34180e5f2b 100644 --- a/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts +++ b/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts @@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { PollVotesRepository, NotesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; +import { CacheService } from '@/core/CacheService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; @@ -24,6 +25,7 @@ export class EndedPollNotificationProcessorService { @Inject(DI.pollVotesRepository) private pollVotesRepository: PollVotesRepository, + private cacheService: CacheService, private notificationService: NotificationService, private queueLoggerService: QueueLoggerService, ) { @@ -47,9 +49,12 @@ export class EndedPollNotificationProcessorService { const userIds = [...new Set([note.userId, ...votes.map(v => v.userId)])]; for (const userId of userIds) { - this.notificationService.createNotification(userId, 'pollEnded', { - noteId: note.id, - }); + const profile = await this.cacheService.userProfileCache.fetch(userId); + if (profile.userHost === null) { + this.notificationService.createNotification(userId, 'pollEnded', { + noteId: note.id, + }); + } } } } diff --git a/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts index 88c4ea29c0..b3111865ad 100644 --- a/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts @@ -14,6 +14,7 @@ import { DriveService } from '@/core/DriveService.js'; import { bindThis } from '@/decorators.js'; import { createTemp } from '@/misc/create-temp.js'; import { UtilityService } from '@/core/UtilityService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type { DBExportAntennasData } from '../types.js'; import type * as Bull from 'bullmq'; @@ -35,6 +36,7 @@ export class ExportAntennasProcessorService { private driveService: DriveService, private utilityService: UtilityService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-antennas'); } @@ -95,6 +97,11 @@ export class ExportAntennasProcessorService { const fileName = 'antennas-' + DateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.json'; const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'json' }); this.logger.succ('Exported to: ' + driveFile.id); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'antenna', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts index 6ec3c18786..ecc439db69 100644 --- a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts @@ -13,6 +13,7 @@ import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; import { UtilityService } from '@/core/UtilityService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -30,6 +31,7 @@ export class ExportBlockingProcessorService { private blockingsRepository: BlockingsRepository, private utilityService: UtilityService, + private notificationService: NotificationService, private driveService: DriveService, private queueLoggerService: QueueLoggerService, ) { @@ -109,6 +111,11 @@ export class ExportBlockingProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'csv' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'blocking', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportClipsProcessorService.ts b/packages/backend/src/queue/processors/ExportClipsProcessorService.ts index 01eab26e96..583ddbb745 100644 --- a/packages/backend/src/queue/processors/ExportClipsProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportClipsProcessorService.ts @@ -19,6 +19,7 @@ import { bindThis } from '@/decorators.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { Packed } from '@/misc/json-schema.js'; import { IdService } from '@/core/IdService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; import type { DbJobDataWithUser } from '../types.js'; @@ -43,6 +44,7 @@ export class ExportClipsProcessorService { private driveService: DriveService, private queueLoggerService: QueueLoggerService, private idService: IdService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-clips'); } @@ -79,6 +81,11 @@ export class ExportClipsProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'json' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'clip', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts index e4eb4791bd..e237cd4975 100644 --- a/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts @@ -16,6 +16,7 @@ import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp, createTempDir } from '@/misc/create-temp.js'; import { DownloadService } from '@/core/DownloadService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -37,6 +38,7 @@ export class ExportCustomEmojisProcessorService { private driveService: DriveService, private downloadService: DownloadService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-custom-emojis'); } @@ -134,6 +136,12 @@ export class ExportCustomEmojisProcessorService { const driveFile = await this.driveService.addFile({ user, path: archivePath, name: fileName, force: true }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'customEmoji', + fileId: driveFile.id, + }); + cleanup(); archiveCleanup(); resolve(); diff --git a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts index 7bb626dd31..b81feece01 100644 --- a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts @@ -16,6 +16,7 @@ import type { MiPoll } from '@/models/Poll.js'; import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; import type { DbJobDataWithUser } from '../types.js'; @@ -37,6 +38,7 @@ export class ExportFavoritesProcessorService { private driveService: DriveService, private queueLoggerService: QueueLoggerService, private idService: IdService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-favorites'); } @@ -123,6 +125,11 @@ export class ExportFavoritesProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'json' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'favorite', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts index 1cc80e66d7..903f962515 100644 --- a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts @@ -14,6 +14,7 @@ import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; import type { MiFollowing } from '@/models/Following.js'; import { UtilityService } from '@/core/UtilityService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -36,6 +37,7 @@ export class ExportFollowingProcessorService { private utilityService: UtilityService, private driveService: DriveService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-following'); } @@ -113,6 +115,11 @@ export class ExportFollowingProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'csv' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'following', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts index 243b74f2c2..f9867ade29 100644 --- a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts @@ -13,6 +13,7 @@ import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; import { UtilityService } from '@/core/UtilityService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -32,6 +33,7 @@ export class ExportMutingProcessorService { private utilityService: UtilityService, private driveService: DriveService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-muting'); } @@ -110,6 +112,11 @@ export class ExportMutingProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'csv' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'muting', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts index c7611012d7..9e2b678219 100644 --- a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts @@ -18,6 +18,7 @@ import { bindThis } from '@/decorators.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { Packed } from '@/misc/json-schema.js'; import { IdService } from '@/core/IdService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { JsonArrayStream } from '@/misc/JsonArrayStream.js'; import { FileWriterStream } from '@/misc/FileWriterStream.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; @@ -112,6 +113,7 @@ export class ExportNotesProcessorService { private queueLoggerService: QueueLoggerService, private driveFileEntityService: DriveFileEntityService, private idService: IdService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-notes'); } @@ -150,6 +152,11 @@ export class ExportNotesProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'json' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'note', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts index ee87cff5d3..c483d79854 100644 --- a/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts @@ -13,6 +13,7 @@ import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; import { UtilityService } from '@/core/UtilityService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; @@ -35,6 +36,7 @@ export class ExportUserListsProcessorService { private utilityService: UtilityService, private driveService: DriveService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('export-user-lists'); } @@ -89,6 +91,11 @@ export class ExportUserListsProcessorService { const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true, ext: 'csv' }); this.logger.succ(`Exported to: ${driveFile.id}`); + + this.notificationService.createNotification(user.id, 'exportCompleted', { + exportedEntity: 'userList', + fileId: driveFile.id, + }); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts index 171809d25c..9e1b8fee70 100644 --- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts @@ -87,23 +87,30 @@ export class ImportCustomEmojisProcessorService { await this.emojisRepository.delete({ name: emojiInfo.name, }); - const driveFile = await this.driveService.addFile({ - user: null, - path: emojiPath, - name: record.fileName, - force: true, - }); - await this.customEmojiService.add({ - name: emojiInfo.name, - category: emojiInfo.category, - host: null, - aliases: emojiInfo.aliases, - driveFile, - license: emojiInfo.license, - isSensitive: emojiInfo.isSensitive, - localOnly: emojiInfo.localOnly, - roleIdsThatCanBeUsedThisEmojiAsReaction: [], - }); + try { + const driveFile = await this.driveService.addFile({ + user: null, + path: emojiPath, + name: record.fileName, + force: true, + }); + await this.customEmojiService.add({ + name: emojiInfo.name, + category: emojiInfo.category, + host: null, + aliases: emojiInfo.aliases, + driveFile, + license: emojiInfo.license, + isSensitive: emojiInfo.isSensitive, + localOnly: emojiInfo.localOnly, + roleIdsThatCanBeUsedThisEmojiAsReaction: [], + }); + } catch (e) { + if (e instanceof Error || typeof e === 'string') { + this.logger.error(`couldn't import ${emojiPath} for ${emojiInfo.name}: ${e}`); + } + continue; + } } cleanup(); diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index fa7009f8f5..a77c968395 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -4,11 +4,10 @@ */ import { URL } from 'node:url'; -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import httpSignature from '@peertube/http-signature'; import * as Bull from 'bullmq'; import type Logger from '@/logger.js'; -import { MetaService } from '@/core/MetaService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js'; import InstanceChart from '@/core/chart/charts/instance.js'; @@ -26,16 +25,28 @@ import { JsonLdService } from '@/core/activitypub/JsonLdService.js'; import { ApInboxService } from '@/core/activitypub/ApInboxService.js'; import { bindThis } from '@/decorators.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { CollapsedQueue } from '@/misc/collapsed-queue.js'; +import { MiNote } from '@/models/Note.js'; +import { MiMeta } from '@/models/Meta.js'; +import { DI } from '@/di-symbols.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type { InboxJobData } from '../types.js'; +type UpdateInstanceJob = { + latestRequestReceivedAt: Date, + shouldUnsuspend: boolean, +}; + @Injectable() -export class InboxProcessorService { +export class InboxProcessorService implements OnApplicationShutdown { private logger: Logger; + private updateInstanceQueue: CollapsedQueue; constructor( + @Inject(DI.meta) + private meta: MiMeta, + private utilityService: UtilityService, - private metaService: MetaService, private apInboxService: ApInboxService, private federatedInstanceService: FederatedInstanceService, private fetchInstanceMetadataService: FetchInstanceMetadataService, @@ -48,6 +59,7 @@ export class InboxProcessorService { private queueLoggerService: QueueLoggerService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('inbox'); + this.updateInstanceQueue = new CollapsedQueue(process.env.NODE_ENV !== 'test' ? 60 * 1000 * 5 : 0, this.collapseUpdateInstanceJobs, this.performUpdateInstance); } @bindThis @@ -63,9 +75,7 @@ export class InboxProcessorService { const host = this.utilityService.toPuny(new URL(signature.keyId).hostname); - // ブロックしてたら中断 - const meta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(meta.blockedHosts, host)) { + if (!this.utilityService.isFederationAllowedHost(host)) { return `Blocked request: ${host}`; } @@ -164,9 +174,8 @@ export class InboxProcessorService { throw new Bull.UnrecoverableError(`skip: LD-Signature user(${authUser.user.uri}) !== activity.actor(${activity.actor})`); } - // ブロックしてたら中断 const ldHost = this.utilityService.extractDbHost(authUser.user.uri); - if (this.utilityService.isBlockedHost(meta.blockedHosts, ldHost)) { + if (!this.utilityService.isFederationAllowedHost(ldHost)) { throw new Bull.UnrecoverableError(`Blocked request: ${ldHost}`); } } else { @@ -185,11 +194,9 @@ export class InboxProcessorService { // Update stats this.federatedInstanceService.fetch(authUser.user.host).then(i => { - this.federatedInstanceService.update(i.id, { + this.updateInstanceQueue.enqueue(i.id, { latestRequestReceivedAt: new Date(), - isNotResponding: false, - // もしサーバーが死んでるために配信が止まっていた場合には自動的に復活させてあげる - suspensionState: i.suspensionState === 'autoSuspendedForNotResponding' ? 'none' : undefined, + shouldUnsuspend: i.suspensionState === 'autoSuspendedForNotResponding', }); this.fetchInstanceMetadataService.fetchInstanceMetadata(i); @@ -197,7 +204,7 @@ export class InboxProcessorService { this.apRequestChart.inbox(); this.federationChart.inbox(i.host); - if (meta.enableChartsForFederatedInstances) { + if (this.meta.enableChartsForFederatedInstances) { this.instanceChart.requestReceived(i.host); } }); @@ -225,4 +232,36 @@ export class InboxProcessorService { } return 'ok'; } + + @bindThis + public collapseUpdateInstanceJobs(oldJob: UpdateInstanceJob, newJob: UpdateInstanceJob) { + const latestRequestReceivedAt = oldJob.latestRequestReceivedAt < newJob.latestRequestReceivedAt + ? newJob.latestRequestReceivedAt + : oldJob.latestRequestReceivedAt; + const shouldUnsuspend = oldJob.shouldUnsuspend || newJob.shouldUnsuspend; + return { + latestRequestReceivedAt, + shouldUnsuspend, + }; + } + + @bindThis + public async performUpdateInstance(id: string, job: UpdateInstanceJob) { + await this.federatedInstanceService.update(id, { + latestRequestReceivedAt: new Date(), + isNotResponding: false, + // もしサーバーが死んでるために配信が止まっていた場合には自動的に復活させてあげる + suspensionState: job.shouldUnsuspend ? 'none' : undefined, + }); + } + + @bindThis + public async dispose(): Promise { + await this.updateInstanceQueue.performAllNow(); + } + + @bindThis + async onApplicationShutdown(signal?: string) { + await this.dispose(); + } } diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 77a637d895..41b6d2e83d 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -82,7 +82,7 @@ export class FileServerService { .catch(err => this.errorHandler(request, reply, err)); }); fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => { - return await reply.redirect(301, `${this.config.url}/files/${request.params.key}`); + return await reply.redirect(`${this.config.url}/files/${request.params.key}`, 301); }); done(); }); @@ -147,12 +147,12 @@ export class FileServerService { url.searchParams.set('static', '1'); file.cleanup(); - return await reply.redirect(301, url.toString()); + return await reply.redirect(url.toString(), 301); } else if (file.mime.startsWith('video/')) { const externalThumbnail = this.videoProcessingService.getExternalVideoThumbnailUrl(file.url); if (externalThumbnail) { file.cleanup(); - return await reply.redirect(301, externalThumbnail); + return await reply.redirect(externalThumbnail, 301); } image = await this.videoProcessingService.generateVideoThumbnail(file.path); @@ -167,7 +167,7 @@ export class FileServerService { url.searchParams.set('url', file.url); file.cleanup(); - return await reply.redirect(301, url.toString()); + return await reply.redirect(url.toString(), 301); } } @@ -314,8 +314,8 @@ export class FileServerService { } return await reply.redirect( - 301, url.toString(), + 301, ); } diff --git a/packages/backend/src/server/HealthServerService.ts b/packages/backend/src/server/HealthServerService.ts index 2c3ed85925..5980609f02 100644 --- a/packages/backend/src/server/HealthServerService.ts +++ b/packages/backend/src/server/HealthServerService.ts @@ -27,6 +27,9 @@ export class HealthServerService { @Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis, + @Inject(DI.redisForReactions) + private redisForReactions: Redis.Redis, + @Inject(DI.db) private db: DataSource, @@ -43,6 +46,7 @@ export class HealthServerService { this.redisForPub.ping(), this.redisForSub.ping(), this.redisForTimelines.ping(), + this.redisForReactions.ping(), this.db.query('SELECT 1'), ...(this.meilisearch ? [this.meilisearch.health()] : []), ]).then(() => 200, () => 503)); diff --git a/packages/backend/src/server/NodeinfoServerService.ts b/packages/backend/src/server/NodeinfoServerService.ts index cc18997fdc..9a641007ee 100644 --- a/packages/backend/src/server/NodeinfoServerService.ts +++ b/packages/backend/src/server/NodeinfoServerService.ts @@ -134,7 +134,7 @@ export class NodeinfoServerService { return document; }; - const cache = new MemorySingleCache>>(1000 * 60 * 10); + const cache = new MemorySingleCache>>(1000 * 60 * 10); // 10m fastify.get(nodeinfo2_1path, async (request, reply) => { const base = await cache.fetch(() => nodeinfo2(21)); diff --git a/packages/backend/src/server/ServerModule.ts b/packages/backend/src/server/ServerModule.ts index 12d5061985..3ab0b815f2 100644 --- a/packages/backend/src/server/ServerModule.ts +++ b/packages/backend/src/server/ServerModule.ts @@ -46,6 +46,7 @@ import { UserListChannelService } from './api/stream/channels/user-list.js'; import { RoleTimelineChannelService } from './api/stream/channels/role-timeline.js'; import { ReversiChannelService } from './api/stream/channels/reversi.js'; import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js'; +import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.js'; @Module({ imports: [ @@ -71,6 +72,7 @@ import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js AuthenticateService, RateLimiterService, SigninApiService, + SigninWithPasskeyApiService, SigninService, SignupApiService, StreamingApiServerService, diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 9c849480f2..fd2bd3267d 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -13,7 +13,7 @@ import fastifyRawBody from 'fastify-raw-body'; import { IsNull } from 'typeorm'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { Config } from '@/config.js'; -import type { EmojisRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { EmojisRepository, MiMeta, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; @@ -21,7 +21,6 @@ import { genIdenticon } from '@/misc/gen-identicon.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; -import { MetaService } from '@/core/MetaService.js'; import { ActivityPubServerService } from './ActivityPubServerService.js'; import { NodeinfoServerService } from './NodeinfoServerService.js'; import { ApiServerService } from './api/ApiServerService.js'; @@ -44,6 +43,9 @@ export class ServerService implements OnApplicationShutdown { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -53,7 +55,6 @@ export class ServerService implements OnApplicationShutdown { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, - private metaService: MetaService, private userEntityService: UserEntityService, private apiServerService: ApiServerService, private openApiServerService: OpenApiServerService, @@ -165,8 +166,8 @@ export class ServerService implements OnApplicationShutdown { } return await reply.redirect( - 301, url.toString(), + 301, ); }); @@ -193,7 +194,7 @@ export class ServerService implements OnApplicationShutdown { reply.header('Content-Type', 'image/png'); reply.header('Cache-Control', 'public, max-age=86400'); - if ((await this.metaService.fetch()).enableIdenticonGeneration) { + if (this.meta.enableIdenticonGeneration) { return await genIdenticon(request.params.x); } else { return reply.redirect('/static-assets/avatar.png'); diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 47f64f6609..aad833f126 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -13,8 +13,7 @@ import { getIpHash } from '@/misc/get-ip-hash.js'; import type { MiLocalUser, MiUser } from '@/models/User.js'; import type { MiAccessToken } from '@/models/AccessToken.js'; import type Logger from '@/logger.js'; -import type { UserIpsRepository } from '@/models/_.js'; -import { MetaService } from '@/core/MetaService.js'; +import type { MiMeta, UserIpsRepository } from '@/models/_.js'; import { createTemp } from '@/misc/create-temp.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; @@ -40,13 +39,15 @@ export class ApiCallService implements OnApplicationShutdown { private userIpHistoriesClearIntervalId: NodeJS.Timeout; constructor( + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.config) private config: Config, @Inject(DI.userIpsRepository) private userIpsRepository: UserIpsRepository, - private metaService: MetaService, private authenticateService: AuthenticateService, private rateLimiterService: RateLimiterService, private roleService: RoleService, @@ -64,15 +65,6 @@ export class ApiCallService implements OnApplicationShutdown { let statusCode = err.httpStatusCode; if (err.httpStatusCode === 401) { reply.header('WWW-Authenticate', 'Bearer realm="Misskey"'); - } else if (err.kind === 'client') { - reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="invalid_request", error_description="${err.message}"`); - statusCode = statusCode ?? 400; - } else if (err.kind === 'permission') { - // (ROLE_PERMISSION_DENIEDは関係ない) - if (err.code === 'PERMISSION_DENIED') { - reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="insufficient_scope", error_description="${err.message}"`); - } - statusCode = statusCode ?? 403; } else if (err.code === 'RATE_LIMIT_EXCEEDED') { const info: unknown = err.info; const unixEpochInSeconds = Date.now(); @@ -83,6 +75,15 @@ export class ApiCallService implements OnApplicationShutdown { } else { this.logger.warn(`rate limit information has unexpected type ${typeof(err.info?.reset)}`); } + } else if (err.kind === 'client') { + reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="invalid_request", error_description="${err.message}"`); + statusCode = statusCode ?? 400; + } else if (err.kind === 'permission') { + // (ROLE_PERMISSION_DENIEDは関係ない) + if (err.code === 'PERMISSION_DENIED') { + reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="insufficient_scope", error_description="${err.message}"`); + } + statusCode = statusCode ?? 403; } else if (!statusCode) { statusCode = 500; } @@ -199,9 +200,18 @@ export class ApiCallService implements OnApplicationShutdown { return; } - const [path] = await createTemp(); + const [path, cleanup] = await createTemp(); await stream.pipeline(multipartData.file, fs.createWriteStream(path)); + // ファイルサイズが制限を超えていた場合 + // なお truncated はストリームを読み切ってからでないと機能しないため、stream.pipeline より後にある必要がある + if (multipartData.file.truncated) { + cleanup(); + reply.code(413); + reply.send(); + return; + } + const fields = {} as Record; for (const [k, v] of Object.entries(multipartData.fields)) { fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined; @@ -256,9 +266,8 @@ export class ApiCallService implements OnApplicationShutdown { } @bindThis - private async logIp(request: FastifyRequest, user: MiLocalUser) { - const meta = await this.metaService.fetch(); - if (!meta.enableIpLogging) return; + private logIp(request: FastifyRequest, user: MiLocalUser) { + if (!this.meta.enableIpLogging) return; const ip = request.ip; const ips = this.userIpHistories.get(user.id); if (ips == null || !ips.has(ip)) { diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts index 4a5935f930..3a8cb19f01 100644 --- a/packages/backend/src/server/api/ApiServerService.ts +++ b/packages/backend/src/server/api/ApiServerService.ts @@ -8,6 +8,7 @@ import cors from '@fastify/cors'; import multipart from '@fastify/multipart'; import fastifyCookie from '@fastify/cookie'; import { ModuleRef } from '@nestjs/core'; +import { AuthenticationResponseJSON } from '@simplewebauthn/types'; import type { Config } from '@/config.js'; import type { InstancesRepository, AccessTokensRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; @@ -17,6 +18,7 @@ import endpoints from './endpoints.js'; import { ApiCallService } from './ApiCallService.js'; import { SignupApiService } from './SignupApiService.js'; import { SigninApiService } from './SigninApiService.js'; +import { SigninWithPasskeyApiService } from './SigninWithPasskeyApiService.js'; import type { FastifyInstance, FastifyPluginOptions } from 'fastify'; @Injectable() @@ -37,6 +39,7 @@ export class ApiServerService { private apiCallService: ApiCallService, private signupApiService: SignupApiService, private signinApiService: SigninApiService, + private signinWithPasskeyApiService: SigninWithPasskeyApiService, ) { //this.createServer = this.createServer.bind(this); } @@ -49,7 +52,7 @@ export class ApiServerService { fastify.register(multipart, { limits: { - fileSize: this.config.maxFileSize ?? 262144000, + fileSize: this.config.maxFileSize, files: 1, }, }); @@ -115,21 +118,31 @@ export class ApiServerService { 'hcaptcha-response'?: string; 'g-recaptcha-response'?: string; 'turnstile-response'?: string; + 'm-captcha-response'?: string; + 'testcaptcha-response'?: string; } }>('/signup', (request, reply) => this.signupApiService.signup(request, reply)); fastify.post<{ Body: { username: string; - password: string; + password?: string; token?: string; - signature?: string; - authenticatorData?: string; - clientDataJSON?: string; - credentialId?: string; - challengeId?: string; + credential?: AuthenticationResponseJSON; + 'hcaptcha-response'?: string; + 'g-recaptcha-response'?: string; + 'turnstile-response'?: string; + 'm-captcha-response'?: string; + 'testcaptcha-response'?: string; }; - }>('/signin', (request, reply) => this.signinApiService.signin(request, reply)); + }>('/signin-flow', (request, reply) => this.signinApiService.signin(request, reply)); + + fastify.post<{ + Body: { + credential?: AuthenticationResponseJSON; + context?: string; + }; + }>('/signin-with-passkey', (request, reply) => this.signinWithPasskeyApiService.signin(request, reply)); fastify.post<{ Body: { code: string; } }>('/signup-pending', (request, reply) => this.signupApiService.signupPending(request, reply)); diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts index ddef8db987..690ff2e022 100644 --- a/packages/backend/src/server/api/AuthenticateService.ts +++ b/packages/backend/src/server/api/AuthenticateService.ts @@ -37,7 +37,7 @@ export class AuthenticateService implements OnApplicationShutdown { private cacheService: CacheService, ) { - this.appCache = new MemoryKVCache(Infinity); + this.appCache = new MemoryKVCache(1000 * 60 * 60 * 24 * 7); // 1w } @bindThis diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 41576bedaa..3557fa40a5 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -68,6 +68,8 @@ import * as ep___admin_relays_list from './endpoints/admin/relays/list.js'; import * as ep___admin_relays_remove from './endpoints/admin/relays/remove.js'; import * as ep___admin_resetPassword from './endpoints/admin/reset-password.js'; import * as ep___admin_resolveAbuseUserReport from './endpoints/admin/resolve-abuse-user-report.js'; +import * as ep___admin_forwardAbuseUserReport from './endpoints/admin/forward-abuse-user-report.js'; +import * as ep___admin_updateAbuseUserReport from './endpoints/admin/update-abuse-user-report.js'; import * as ep___admin_sendEmail from './endpoints/admin/send-email.js'; import * as ep___admin_serverInfo from './endpoints/admin/server-info.js'; import * as ep___admin_showModerationLogs from './endpoints/admin/show-moderation-logs.js'; @@ -92,6 +94,7 @@ import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webho import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; +import * as ep___admin_systemWebhook_test from './endpoints/admin/system-webhook/test.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -258,6 +261,7 @@ import * as ep___i_webhooks_show from './endpoints/i/webhooks/show.js'; import * as ep___i_webhooks_list from './endpoints/i/webhooks/list.js'; import * as ep___i_webhooks_update from './endpoints/i/webhooks/update.js'; import * as ep___i_webhooks_delete from './endpoints/i/webhooks/delete.js'; +import * as ep___i_webhooks_test from './endpoints/i/webhooks/test.js'; import * as ep___invite_create from './endpoints/invite/create.js'; import * as ep___invite_delete from './endpoints/invite/delete.js'; import * as ep___invite_list from './endpoints/invite/list.js'; @@ -451,6 +455,8 @@ const $admin_relays_list: Provider = { provide: 'ep:admin/relays/list', useClass const $admin_relays_remove: Provider = { provide: 'ep:admin/relays/remove', useClass: ep___admin_relays_remove.default }; const $admin_resetPassword: Provider = { provide: 'ep:admin/reset-password', useClass: ep___admin_resetPassword.default }; const $admin_resolveAbuseUserReport: Provider = { provide: 'ep:admin/resolve-abuse-user-report', useClass: ep___admin_resolveAbuseUserReport.default }; +const $admin_forwardAbuseUserReport: Provider = { provide: 'ep:admin/forward-abuse-user-report', useClass: ep___admin_forwardAbuseUserReport.default }; +const $admin_updateAbuseUserReport: Provider = { provide: 'ep:admin/update-abuse-user-report', useClass: ep___admin_updateAbuseUserReport.default }; const $admin_sendEmail: Provider = { provide: 'ep:admin/send-email', useClass: ep___admin_sendEmail.default }; const $admin_serverInfo: Provider = { provide: 'ep:admin/server-info', useClass: ep___admin_serverInfo.default }; const $admin_showModerationLogs: Provider = { provide: 'ep:admin/show-moderation-logs', useClass: ep___admin_showModerationLogs.default }; @@ -475,6 +481,7 @@ const $admin_systemWebhook_delete: Provider = { provide: 'ep:admin/system-webhoo const $admin_systemWebhook_list: Provider = { provide: 'ep:admin/system-webhook/list', useClass: ep___admin_systemWebhook_list.default }; const $admin_systemWebhook_show: Provider = { provide: 'ep:admin/system-webhook/show', useClass: ep___admin_systemWebhook_show.default }; const $admin_systemWebhook_update: Provider = { provide: 'ep:admin/system-webhook/update', useClass: ep___admin_systemWebhook_update.default }; +const $admin_systemWebhook_test: Provider = { provide: 'ep:admin/system-webhook/test', useClass: ep___admin_systemWebhook_test.default }; const $announcements: Provider = { provide: 'ep:announcements', useClass: ep___announcements.default }; const $announcements_show: Provider = { provide: 'ep:announcements/show', useClass: ep___announcements_show.default }; const $antennas_create: Provider = { provide: 'ep:antennas/create', useClass: ep___antennas_create.default }; @@ -641,6 +648,7 @@ const $i_webhooks_list: Provider = { provide: 'ep:i/webhooks/list', useClass: ep const $i_webhooks_show: Provider = { provide: 'ep:i/webhooks/show', useClass: ep___i_webhooks_show.default }; const $i_webhooks_update: Provider = { provide: 'ep:i/webhooks/update', useClass: ep___i_webhooks_update.default }; const $i_webhooks_delete: Provider = { provide: 'ep:i/webhooks/delete', useClass: ep___i_webhooks_delete.default }; +const $i_webhooks_test: Provider = { provide: 'ep:i/webhooks/test', useClass: ep___i_webhooks_test.default }; const $invite_create: Provider = { provide: 'ep:invite/create', useClass: ep___invite_create.default }; const $invite_delete: Provider = { provide: 'ep:invite/delete', useClass: ep___invite_delete.default }; const $invite_list: Provider = { provide: 'ep:invite/list', useClass: ep___invite_list.default }; @@ -838,6 +846,8 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_relays_remove, $admin_resetPassword, $admin_resolveAbuseUserReport, + $admin_forwardAbuseUserReport, + $admin_updateAbuseUserReport, $admin_sendEmail, $admin_serverInfo, $admin_showModerationLogs, @@ -862,6 +872,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_systemWebhook_list, $admin_systemWebhook_show, $admin_systemWebhook_update, + $admin_systemWebhook_test, $announcements, $announcements_show, $antennas_create, @@ -1028,6 +1039,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $i_webhooks_show, $i_webhooks_update, $i_webhooks_delete, + $i_webhooks_test, $invite_create, $invite_delete, $invite_list, @@ -1219,6 +1231,8 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_relays_remove, $admin_resetPassword, $admin_resolveAbuseUserReport, + $admin_forwardAbuseUserReport, + $admin_updateAbuseUserReport, $admin_sendEmail, $admin_serverInfo, $admin_showModerationLogs, @@ -1243,6 +1257,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_systemWebhook_list, $admin_systemWebhook_show, $admin_systemWebhook_update, + $admin_systemWebhook_test, $announcements, $announcements_show, $antennas_create, @@ -1409,6 +1424,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $i_webhooks_show, $i_webhooks_update, $i_webhooks_delete, + $i_webhooks_test, $invite_create, $invite_delete, $invite_list, diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index edac9b3beb..1d983ca4bc 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -5,12 +5,14 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; -import * as OTPAuth from 'otpauth'; import { IsNull } from 'typeorm'; +import * as Misskey from 'misskey-js'; import { DI } from '@/di-symbols.js'; import type { + MiMeta, SigninsRepository, UserProfilesRepository, + UserSecurityKeysRepository, UsersRepository, } from '@/models/_.js'; import type { Config } from '@/config.js'; @@ -20,6 +22,8 @@ import { IdService } from '@/core/IdService.js'; import { bindThis } from '@/decorators.js'; import { WebAuthnService } from '@/core/WebAuthnService.js'; import { UserAuthService } from '@/core/UserAuthService.js'; +import { CaptchaService } from '@/core/CaptchaService.js'; +import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; import { RateLimiterService } from './RateLimiterService.js'; import { SigninService } from './SigninService.js'; import type { AuthenticationResponseJSON } from '@simplewebauthn/types'; @@ -31,12 +35,18 @@ export class SigninApiService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + @Inject(DI.userSecurityKeysRepository) + private userSecurityKeysRepository: UserSecurityKeysRepository, + @Inject(DI.signinsRepository) private signinsRepository: SigninsRepository, @@ -45,6 +55,7 @@ export class SigninApiService { private signinService: SigninService, private userAuthService: UserAuthService, private webAuthnService: WebAuthnService, + private captchaService: CaptchaService, ) { } @@ -53,9 +64,14 @@ export class SigninApiService { request: FastifyRequest<{ Body: { username: string; - password: string; + password?: string; token?: string; credential?: AuthenticationResponseJSON; + 'hcaptcha-response'?: string; + 'g-recaptcha-response'?: string; + 'turnstile-response'?: string; + 'm-captcha-response'?: string; + 'testcaptcha-response'?: string; }; }>, reply: FastifyReply, @@ -92,11 +108,6 @@ export class SigninApiService { return; } - if (typeof password !== 'string') { - reply.code(400); - return; - } - if (token != null && typeof token !== 'string') { reply.code(400); return; @@ -121,11 +132,32 @@ export class SigninApiService { } const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); + const securityKeysAvailable = await this.userSecurityKeysRepository.countBy({ userId: user.id }).then(result => result >= 1); + + if (password == null) { + reply.code(200); + if (profile.twoFactorEnabled) { + return { + finished: false, + next: 'password', + } satisfies Misskey.entities.SigninFlowResponse; + } else { + return { + finished: false, + next: 'captcha', + } satisfies Misskey.entities.SigninFlowResponse; + } + } + + if (typeof password !== 'string') { + reply.code(400); + return; + } // Compare password const same = await bcrypt.compare(password, profile.password!); - const fail = async (status?: number, failure?: { id: string }) => { + const fail = async (status?: number, failure?: { id: string; }) => { // Append signin history await this.signinsRepository.insert({ id: this.idService.gen(), @@ -139,6 +171,38 @@ export class SigninApiService { }; if (!profile.twoFactorEnabled) { + if (process.env.NODE_ENV !== 'test') { + if (this.meta.enableHcaptcha && this.meta.hcaptchaSecretKey) { + await this.captchaService.verifyHcaptcha(this.meta.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + + if (this.meta.enableMcaptcha && this.meta.mcaptchaSecretKey && this.meta.mcaptchaSitekey && this.meta.mcaptchaInstanceUrl) { + await this.captchaService.verifyMcaptcha(this.meta.mcaptchaSecretKey, this.meta.mcaptchaSitekey, this.meta.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + + if (this.meta.enableRecaptcha && this.meta.recaptchaSecretKey) { + await this.captchaService.verifyRecaptcha(this.meta.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + + if (this.meta.enableTurnstile && this.meta.turnstileSecretKey) { + await this.captchaService.verifyTurnstile(this.meta.turnstileSecretKey, body['turnstile-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + + if (this.meta.enableTestcaptcha) { + await this.captchaService.verifyTestcaptcha(body['testcaptcha-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + } + if (same) { return this.signinService.signin(request, reply, user); } else { @@ -180,7 +244,7 @@ export class SigninApiService { id: '93b86c4b-72f9-40eb-9815-798928603d1e', }); } - } else { + } else if (securityKeysAvailable) { if (!same && !profile.usePasswordLessLogin) { return await fail(403, { id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c', @@ -190,7 +254,23 @@ export class SigninApiService { const authRequest = await this.webAuthnService.initiateAuthentication(user.id); reply.code(200); - return authRequest; + return { + finished: false, + next: 'passkey', + authRequest, + } satisfies Misskey.entities.SigninFlowResponse; + } else { + if (!same || !profile.twoFactorEnabled) { + return await fail(403, { + id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c', + }); + } else { + reply.code(200); + return { + finished: false, + next: 'totp', + } satisfies Misskey.entities.SigninFlowResponse; + } } // never get here } diff --git a/packages/backend/src/server/api/SigninService.ts b/packages/backend/src/server/api/SigninService.ts index 70306c3113..640356b50c 100644 --- a/packages/backend/src/server/api/SigninService.ts +++ b/packages/backend/src/server/api/SigninService.ts @@ -4,13 +4,16 @@ */ import { Inject, Injectable } from '@nestjs/common'; +import * as Misskey from 'misskey-js'; import { DI } from '@/di-symbols.js'; -import type { SigninsRepository } from '@/models/_.js'; +import type { SigninsRepository, UserProfilesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import type { MiLocalUser } from '@/models/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { SigninEntityService } from '@/core/entities/SigninEntityService.js'; import { bindThis } from '@/decorators.js'; +import { EmailService } from '@/core/EmailService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import type { FastifyRequest, FastifyReply } from 'fastify'; @Injectable() @@ -19,7 +22,12 @@ export class SigninService { @Inject(DI.signinsRepository) private signinsRepository: SigninsRepository, + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + private signinEntityService: SigninEntityService, + private emailService: EmailService, + private notificationService: NotificationService, private idService: IdService, private globalEventService: GlobalEventService, ) { @@ -28,7 +36,8 @@ export class SigninService { @bindThis public signin(request: FastifyRequest, reply: FastifyReply, user: MiLocalUser) { setImmediate(async () => { - // Append signin history + this.notificationService.createNotification(user.id, 'login', {}); + const record = await this.signinsRepository.insertOne({ id: this.idService.gen(), userId: user.id, @@ -37,15 +46,22 @@ export class SigninService { success: true, }); - // Publish signin event this.globalEventService.publishMainStream(user.id, 'signin', await this.signinEntityService.pack(record)); + + const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); + if (profile.email && profile.emailVerified) { + this.emailService.sendEmail(profile.email, 'New login / ログインがありました', + 'There is a new login. If you do not recognize this login, update the security status of your account, including changing your password. / 新しいログインがありました。このログインに心当たりがない場合は、パスワードを変更するなど、アカウントのセキュリティ状態を更新してください。', + 'There is a new login. If you do not recognize this login, update the security status of your account, including changing your password. / 新しいログインがありました。このログインに心当たりがない場合は、パスワードを変更するなど、アカウントのセキュリティ状態を更新してください。'); + } }); reply.code(200); return { + finished: true, id: user.id, - i: user.token, - }; + i: user.token!, + } satisfies Misskey.entities.SigninFlowResponse; } } diff --git a/packages/backend/src/server/api/SigninWithPasskeyApiService.ts b/packages/backend/src/server/api/SigninWithPasskeyApiService.ts new file mode 100644 index 0000000000..9ba23c54e2 --- /dev/null +++ b/packages/backend/src/server/api/SigninWithPasskeyApiService.ts @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { randomUUID } from 'crypto'; +import { Inject, Injectable } from '@nestjs/common'; +import { IsNull } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { + SigninsRepository, + UserProfilesRepository, + UsersRepository, +} from '@/models/_.js'; +import type { Config } from '@/config.js'; +import { getIpHash } from '@/misc/get-ip-hash.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; +import { IdService } from '@/core/IdService.js'; +import { bindThis } from '@/decorators.js'; +import { WebAuthnService } from '@/core/WebAuthnService.js'; +import Logger from '@/logger.js'; +import { LoggerService } from '@/core/LoggerService.js'; +import type { IdentifiableError } from '@/misc/identifiable-error.js'; +import { RateLimiterService } from './RateLimiterService.js'; +import { SigninService } from './SigninService.js'; +import type { AuthenticationResponseJSON } from '@simplewebauthn/types'; +import type { FastifyReply, FastifyRequest } from 'fastify'; + +@Injectable() +export class SigninWithPasskeyApiService { + private logger: Logger; + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + + @Inject(DI.signinsRepository) + private signinsRepository: SigninsRepository, + + private idService: IdService, + private rateLimiterService: RateLimiterService, + private signinService: SigninService, + private webAuthnService: WebAuthnService, + private loggerService: LoggerService, + ) { + this.logger = this.loggerService.getLogger('PasskeyAuth'); + } + + @bindThis + public async signin( + request: FastifyRequest<{ + Body: { + credential?: AuthenticationResponseJSON; + context?: string; + }; + }>, + reply: FastifyReply, + ) { + reply.header('Access-Control-Allow-Origin', this.config.url); + reply.header('Access-Control-Allow-Credentials', 'true'); + + const body = request.body; + const credential = body['credential']; + + function error(status: number, error: { id: string }) { + reply.code(status); + return { error }; + } + + const fail = async (userId: MiUser['id'], status?: number, failure?: { id: string }) => { + // Append signin history + await this.signinsRepository.insert({ + id: this.idService.gen(), + userId: userId, + ip: request.ip, + headers: request.headers as any, + success: false, + }); + return error(status ?? 500, failure ?? { id: '4e30e80c-e338-45a0-8c8f-44455efa3b76' }); + }; + + try { + // Not more than 1 API call per 250ms and not more than 100 attempts per 30min + // NOTE: 1 Sign-in require 2 API calls + await this.rateLimiterService.limit({ key: 'signin-with-passkey', duration: 60 * 30 * 1000, max: 200, minInterval: 250 }, getIpHash(request.ip)); + } catch (err) { + reply.code(429); + return { + error: { + message: 'Too many failed attempts to sign in. Try again later.', + code: 'TOO_MANY_AUTHENTICATION_FAILURES', + id: '22d05606-fbcf-421a-a2db-b32610dcfd1b', + }, + }; + } + + // Initiate Passkey Auth challenge with context + if (!credential) { + const context = randomUUID(); + this.logger.info(`Initiate Passkey challenge: context: ${context}`); + const authChallengeOptions = { + option: await this.webAuthnService.initiateSignInWithPasskeyAuthentication(context), + context: context, + }; + reply.code(200); + return authChallengeOptions; + } + + const context = body.context; + if (!context || typeof context !== 'string') { + // If try Authentication without context + return error(400, { + id: '1658cc2e-4495-461f-aee4-d403cdf073c1', + }); + } + + this.logger.debug(`Try Sign-in with Passkey: context: ${context}`); + + let authorizedUserId: MiUser['id'] | null; + try { + authorizedUserId = await this.webAuthnService.verifySignInWithPasskeyAuthentication(context, credential); + } catch (err) { + this.logger.warn(`Passkey challenge Verify error! : ${err}`); + const errorId = (err as IdentifiableError).id; + return error(403, { + id: errorId, + }); + } + + if (!authorizedUserId) { + return error(403, { + id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c', + }); + } + + // Fetch user + const user = await this.usersRepository.findOneBy({ + id: authorizedUserId, + host: IsNull(), + }) as MiLocalUser | null; + + if (user == null) { + return error(403, { + id: '652f899f-66d4-490e-993e-6606c8ec04c3', + }); + } + + if (user.isSuspended) { + return error(403, { + id: 'e03a5f46-d309-4865-9b69-56282d94e1eb', + }); + } + + const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); + + // Authentication was successful, but passwordless login is not enabled + if (!profile.usePasswordLessLogin) { + return await fail(user.id, 403, { + id: '2d84773e-f7b7-4d0b-8f72-bb69b584c912', + }); + } + + const signinResponse = this.signinService.signin(request, reply, user); + return { + signinResponse: signinResponse, + }; + } +} diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 632b0c62bc..3ec5e5d3e6 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -7,9 +7,8 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket } from '@/models/_.js'; +import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket, MiMeta } from '@/models/_.js'; import type { Config } from '@/config.js'; -import { MetaService } from '@/core/MetaService.js'; import { CaptchaService } from '@/core/CaptchaService.js'; import { IdService } from '@/core/IdService.js'; import { SignupService } from '@/core/SignupService.js'; @@ -28,6 +27,9 @@ export class SignupApiService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -45,7 +47,6 @@ export class SignupApiService { private userEntityService: UserEntityService, private idService: IdService, - private metaService: MetaService, private captchaService: CaptchaService, private signupService: SignupService, private signinService: SigninService, @@ -66,37 +67,42 @@ export class SignupApiService { 'g-recaptcha-response'?: string; 'turnstile-response'?: string; 'm-captcha-response'?: string; + 'testcaptcha-response'?: string; } }>, reply: FastifyReply, ) { const body = request.body; - const instance = await this.metaService.fetch(true); - // Verify *Captcha // ただしテスト時はこの機構は障害となるため無効にする if (process.env.NODE_ENV !== 'test') { - if (instance.enableHcaptcha && instance.hcaptchaSecretKey) { - await this.captchaService.verifyHcaptcha(instance.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => { + if (this.meta.enableHcaptcha && this.meta.hcaptchaSecretKey) { + await this.captchaService.verifyHcaptcha(this.meta.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => { throw new FastifyReplyError(400, err); }); } - if (instance.enableMcaptcha && instance.mcaptchaSecretKey && instance.mcaptchaSitekey && instance.mcaptchaInstanceUrl) { - await this.captchaService.verifyMcaptcha(instance.mcaptchaSecretKey, instance.mcaptchaSitekey, instance.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => { + if (this.meta.enableMcaptcha && this.meta.mcaptchaSecretKey && this.meta.mcaptchaSitekey && this.meta.mcaptchaInstanceUrl) { + await this.captchaService.verifyMcaptcha(this.meta.mcaptchaSecretKey, this.meta.mcaptchaSitekey, this.meta.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => { throw new FastifyReplyError(400, err); }); } - if (instance.enableRecaptcha && instance.recaptchaSecretKey) { - await this.captchaService.verifyRecaptcha(instance.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => { + if (this.meta.enableRecaptcha && this.meta.recaptchaSecretKey) { + await this.captchaService.verifyRecaptcha(this.meta.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => { throw new FastifyReplyError(400, err); }); } - if (instance.enableTurnstile && instance.turnstileSecretKey) { - await this.captchaService.verifyTurnstile(instance.turnstileSecretKey, body['turnstile-response']).catch(err => { + if (this.meta.enableTurnstile && this.meta.turnstileSecretKey) { + await this.captchaService.verifyTurnstile(this.meta.turnstileSecretKey, body['turnstile-response']).catch(err => { + throw new FastifyReplyError(400, err); + }); + } + + if (this.meta.enableTestcaptcha) { + await this.captchaService.verifyTestcaptcha(body['testcaptcha-response']).catch(err => { throw new FastifyReplyError(400, err); }); } @@ -108,7 +114,7 @@ export class SignupApiService { const invitationCode = body['invitationCode']; const emailAddress = body['emailAddress']; - if (instance.emailRequiredForSignup) { + if (this.meta.emailRequiredForSignup) { if (emailAddress == null || typeof emailAddress !== 'string') { reply.code(400); return; @@ -123,7 +129,7 @@ export class SignupApiService { let ticket: MiRegistrationTicket | null = null; - if (instance.disableRegistration) { + if (this.meta.disableRegistration) { if (invitationCode == null || typeof invitationCode !== 'string') { reply.code(400); return; @@ -144,7 +150,7 @@ export class SignupApiService { } // メアド認証が有効の場合 - if (instance.emailRequiredForSignup) { + if (this.meta.emailRequiredForSignup) { // メアド認証済みならエラー if (ticket.usedBy) { reply.code(400); @@ -162,7 +168,7 @@ export class SignupApiService { } } - if (instance.emailRequiredForSignup) { + if (this.meta.emailRequiredForSignup) { if (await this.usersRepository.exists({ where: { usernameLower: username.toLowerCase(), host: IsNull() } })) { throw new FastifyReplyError(400, 'DUPLICATED_USERNAME'); } @@ -172,7 +178,7 @@ export class SignupApiService { throw new FastifyReplyError(400, 'USED_USERNAME'); } - const isPreserved = instance.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase()); + const isPreserved = this.meta.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase()); if (isPreserved) { throw new FastifyReplyError(400, 'DENIED_USERNAME'); } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 3dfb7fdad4..49b07d6ced 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -74,6 +74,8 @@ import * as ep___admin_relays_list from './endpoints/admin/relays/list.js'; import * as ep___admin_relays_remove from './endpoints/admin/relays/remove.js'; import * as ep___admin_resetPassword from './endpoints/admin/reset-password.js'; import * as ep___admin_resolveAbuseUserReport from './endpoints/admin/resolve-abuse-user-report.js'; +import * as ep___admin_forwardAbuseUserReport from './endpoints/admin/forward-abuse-user-report.js'; +import * as ep___admin_updateAbuseUserReport from './endpoints/admin/update-abuse-user-report.js'; import * as ep___admin_sendEmail from './endpoints/admin/send-email.js'; import * as ep___admin_serverInfo from './endpoints/admin/server-info.js'; import * as ep___admin_showModerationLogs from './endpoints/admin/show-moderation-logs.js'; @@ -98,6 +100,7 @@ import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webho import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; +import * as ep___admin_systemWebhook_test from './endpoints/admin/system-webhook/test.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -264,6 +267,7 @@ import * as ep___i_webhooks_show from './endpoints/i/webhooks/show.js'; import * as ep___i_webhooks_list from './endpoints/i/webhooks/list.js'; import * as ep___i_webhooks_update from './endpoints/i/webhooks/update.js'; import * as ep___i_webhooks_delete from './endpoints/i/webhooks/delete.js'; +import * as ep___i_webhooks_test from './endpoints/i/webhooks/test.js'; import * as ep___invite_create from './endpoints/invite/create.js'; import * as ep___invite_delete from './endpoints/invite/delete.js'; import * as ep___invite_list from './endpoints/invite/list.js'; @@ -455,6 +459,8 @@ const eps = [ ['admin/relays/remove', ep___admin_relays_remove], ['admin/reset-password', ep___admin_resetPassword], ['admin/resolve-abuse-user-report', ep___admin_resolveAbuseUserReport], + ['admin/forward-abuse-user-report', ep___admin_forwardAbuseUserReport], + ['admin/update-abuse-user-report', ep___admin_updateAbuseUserReport], ['admin/send-email', ep___admin_sendEmail], ['admin/server-info', ep___admin_serverInfo], ['admin/show-moderation-logs', ep___admin_showModerationLogs], @@ -479,6 +485,7 @@ const eps = [ ['admin/system-webhook/list', ep___admin_systemWebhook_list], ['admin/system-webhook/show', ep___admin_systemWebhook_show], ['admin/system-webhook/update', ep___admin_systemWebhook_update], + ['admin/system-webhook/test', ep___admin_systemWebhook_test], ['announcements', ep___announcements], ['announcements/show', ep___announcements_show], ['antennas/create', ep___antennas_create], @@ -645,6 +652,7 @@ const eps = [ ['i/webhooks/show', ep___i_webhooks_show], ['i/webhooks/update', ep___i_webhooks_update], ['i/webhooks/delete', ep___i_webhooks_delete], + ['i/webhooks/test', ep___i_webhooks_test], ['invite/create', ep___invite_create], ['invite/delete', ep___invite_delete], ['invite/list', ep___invite_list], diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts index cf3f257ca6..0dbfaae054 100644 --- a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts +++ b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts @@ -71,9 +71,22 @@ export const meta = { }, assignee: { type: 'object', - nullable: true, optional: true, + nullable: true, optional: false, ref: 'UserDetailedNotMe', }, + forwarded: { + type: 'boolean', + nullable: false, optional: false, + }, + resolvedAs: { + type: 'string', + nullable: true, optional: false, + enum: ['accept', 'reject', null], + }, + moderationNote: { + type: 'string', + nullable: false, optional: false, + }, }, }, }, @@ -88,7 +101,6 @@ export const paramDef = { state: { type: 'string', nullable: true, default: null }, reporterOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'combined' }, targetUserOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'combined' }, - forwarded: { type: 'boolean', default: false }, }, required: [], } as const; diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts index a7e8a3b018..d30131a62f 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts @@ -12,11 +12,27 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; import { localUsernameSchema, passwordSchema } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; +import type { Config } from '@/config.js'; +import { ApiError } from '@/server/api/error.js'; import { Packed } from '@/misc/json-schema.js'; export const meta = { tags: ['admin'], + errors: { + accessDenied: { + message: 'Access denied.', + code: 'ACCESS_DENIED', + id: '1fb7cb09-d46a-4fff-b8df-057708cce513', + }, + + wrongInitialPassword: { + message: 'Initial password is incorrect.', + code: 'INCORRECT_INITIAL_PASSWORD', + id: '97147c55-1ae1-4f6f-91d6-e1c3e0e76d62', + }, + }, + res: { type: 'object', optional: false, nullable: false, @@ -35,6 +51,7 @@ export const paramDef = { properties: { username: localUsernameSchema, password: passwordSchema, + setupPassword: { type: 'string', nullable: true }, }, required: ['username', 'password'], } as const; @@ -42,6 +59,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.config) + private config: Config, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -52,7 +72,23 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, _me, token) => { const me = _me ? await this.usersRepository.findOneByOrFail({ id: _me.id }) : null; const realUsers = await this.instanceActorService.realLocalUsersPresent(); - if ((realUsers && !me?.isRoot) || token !== null) throw new Error('access denied'); + + if (!realUsers && me == null && token == null) { + // 初回セットアップの場合 + if (this.config.setupPassword != null) { + // 初期パスワードが設定されている場合 + if (ps.setupPassword !== this.config.setupPassword) { + // 初期パスワードが違う場合 + throw new ApiError(meta.errors.wrongInitialPassword); + } + } else if (ps.setupPassword != null && ps.setupPassword.trim() !== '') { + // 初期パスワードが設定されていないのに初期パスワードが入力された場合 + throw new ApiError(meta.errors.wrongInitialPassword); + } + } else if ((realUsers && !me?.isRoot) || token !== null) { + // 初回セットアップではなく、管理者でない場合 or 外部トークンを使用している場合 + throw new ApiError(meta.errors.accessDenied); + } const { account, secret } = await this.signupService.signup({ username: ps.username, diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts index 4074e416b8..01dea703a3 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts @@ -7,9 +7,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository } from '@/models/_.js'; import { QueueService } from '@/core/QueueService.js'; -import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { DeleteAccountService } from '@/core/DeleteAccountService.js'; export const meta = { tags: ['admin'], @@ -33,9 +33,7 @@ export default class extends Endpoint { // eslint- @Inject(DI.usersRepository) private usersRepository: UsersRepository, - private userEntityService: UserEntityService, - private queueService: QueueService, - private userSuspendService: UserSuspendService, + private deleteAccoountService: DeleteAccountService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy({ id: ps.userId }); @@ -48,22 +46,7 @@ export default class extends Endpoint { // eslint- throw new Error('cannot delete a root account'); } - if (this.userEntityService.isLocalUser(user)) { - // 物理削除する前にDelete activityを送信する - await this.userSuspendService.doPostSuspend(user).catch(err => {}); - - this.queueService.createDeleteAccountJob(user, { - soft: false, - }); - } else { - this.queueService.createDeleteAccountJob(user, { - soft: true, // リモートユーザーの削除は、完全にDBから物理削除してしまうと再度連合してきてアカウントが復活する可能性があるため、soft指定する - }); - } - - await this.usersRepository.update(user.id, { - isDeleted: true, - }); + await this.deleteAccoountService.deleteAccount(user); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts index 87eaad31a3..7596bf44e3 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts @@ -69,6 +69,7 @@ export const paramDef = { sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, userId: { type: 'string', format: 'misskey:id', nullable: true }, + status: { type: 'string', enum: ['all', 'active', 'archived'], default: 'active' }, }, required: [], } as const; @@ -87,7 +88,13 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); - query.andWhere('announcement.isActive = true'); + + if (ps.status === 'archived') { + query.andWhere('announcement.isActive = false'); + } else if (ps.status === 'active') { + query.andWhere('announcement.isActive = true'); + } + if (ps.userId) { query.andWhere('announcement.userId = :userId', { userId: ps.userId }); } else { diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index 459d8880fa..a7136d8c8c 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -61,7 +61,7 @@ export const meta = { name: { type: 'string', optional: false, nullable: false, - example: 'lenna.jpg', + example: '192.jpg', }, type: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 22609a16a3..212cba5c5d 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; -import type { DriveFilesRepository } from '@/models/_.js'; +import type { DriveFilesRepository, MiEmoji } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; @@ -78,25 +78,14 @@ export default class extends Endpoint { // eslint- if (driveFile == null) throw new ApiError(meta.errors.noSuchFile); } - let emojiId; - if (ps.id) { - emojiId = ps.id; - const emoji = await this.customEmojiService.getEmojiById(ps.id); - if (!emoji) throw new ApiError(meta.errors.noSuchEmoji); - if (ps.name && (ps.name !== emoji.name)) { - const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name); - if (isDuplicate) throw new ApiError(meta.errors.sameNameEmojiExists); - } - } else { - if (!ps.name) throw new Error('Invalid Params unexpectedly passed. This is a BUG. Please report it to the development team.'); - const emoji = await this.customEmojiService.getEmojiByName(ps.name); - if (!emoji) throw new ApiError(meta.errors.noSuchEmoji); - emojiId = emoji.id; - } + // JSON schemeのanyOfの型変換がうまくいっていないらしい + const required = { id: ps.id, name: ps.name } as + | { id: MiEmoji['id']; name?: string } + | { id?: MiEmoji['id']; name: string }; - await this.customEmojiService.update(emojiId, { + const error = await this.customEmojiService.update({ + ...required, driveFile, - name: ps.name, category: ps.category, aliases: ps.aliases, license: ps.license, @@ -104,6 +93,14 @@ export default class extends Endpoint { // eslint- localOnly: ps.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction, }, me); + + switch (error) { + case null: return; + case 'NO_SUCH_EMOJI': throw new ApiError(meta.errors.noSuchEmoji); + case 'SAME_NAME_EMOJI_EXISTS': throw new ApiError(meta.errors.sameNameEmojiExists); + } + // 網羅性チェック + const mustBeNever: never = error; }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/forward-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/forward-abuse-user-report.ts new file mode 100644 index 0000000000..3e42c91fed --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/forward-abuse-user-report.ts @@ -0,0 +1,55 @@ +/* + * 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 type { AbuseUserReportsRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '@/server/api/error.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + kind: 'write:admin:resolve-abuse-user-report', + + errors: { + noSuchAbuseReport: { + message: 'No such abuse report.', + code: 'NO_SUCH_ABUSE_REPORT', + id: '8763e21b-d9bc-40be-acf6-54c1a6986493', + kind: 'server', + httpStatusCode: 404, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + reportId: { type: 'string', format: 'misskey:id' }, + }, + required: ['reportId'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.abuseUserReportsRepository) + private abuseUserReportsRepository: AbuseUserReportsRepository, + private abuseReportService: AbuseReportService, + ) { + super(meta, paramDef, async (ps, me) => { + const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId }); + if (!report) { + throw new ApiError(meta.errors.noSuchAbuseReport); + } + + await this.abuseReportService.forward(report.id, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index eee02a7123..abb3c17be3 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -69,6 +69,10 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + enableTestcaptcha: { + type: 'boolean', + optional: false, nullable: false, + }, swPublickey: { type: 'string', optional: false, nullable: true, @@ -128,6 +132,16 @@ export const meta = { nullable: false, }, }, + mediaSilencedHosts: { + type: 'array', + optional: false, + nullable: false, + items: { + type: 'string', + optional: false, + nullable: false, + }, + }, pinnedUsers: { type: 'array', optional: false, nullable: false, @@ -367,6 +381,10 @@ export const meta = { type: 'number', optional: false, nullable: false, }, + enableReactionsBuffering: { + type: 'boolean', + optional: false, nullable: false, + }, notesPerOneAd: { type: 'number', optional: false, nullable: false, @@ -481,6 +499,18 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + federation: { + type: 'string', + optional: false, nullable: false, + }, + federationHosts: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: false, nullable: false, + }, + }, }, }, } as const; @@ -529,6 +559,7 @@ export default class extends Endpoint { // eslint- recaptchaSiteKey: instance.recaptchaSiteKey, enableTurnstile: instance.enableTurnstile, turnstileSiteKey: instance.turnstileSiteKey, + enableTestcaptcha: instance.enableTestcaptcha, swPublickey: instance.swPublicKey, themeColor: instance.themeColor, mascotImageUrl: instance.mascotImageUrl, @@ -552,6 +583,7 @@ export default class extends Endpoint { // eslint- hiddenTags: instance.hiddenTags, blockedHosts: instance.blockedHosts, silencedHosts: instance.silencedHosts, + mediaSilencedHosts: instance.mediaSilencedHosts, sensitiveWords: instance.sensitiveWords, prohibitedWords: instance.prohibitedWords, preservedUsernames: instance.preservedUsernames, @@ -606,6 +638,7 @@ export default class extends Endpoint { // eslint- perRemoteUserUserTimelineCacheMax: instance.perRemoteUserUserTimelineCacheMax, perUserHomeTimelineCacheMax: instance.perUserHomeTimelineCacheMax, perUserListTimelineCacheMax: instance.perUserListTimelineCacheMax, + enableReactionsBuffering: instance.enableReactionsBuffering, notesPerOneAd: instance.notesPerOneAd, summalyProxy: instance.urlPreviewSummaryProxyUrl, urlPreviewEnabled: instance.urlPreviewEnabled, @@ -614,6 +647,8 @@ export default class extends Endpoint { // eslint- urlPreviewRequireContentLength: instance.urlPreviewRequireContentLength, urlPreviewUserAgent: instance.urlPreviewUserAgent, urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl, + federation: instance.federation, + federationHosts: instance.federationHosts, }; }); } diff --git a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts index 7a3410ffa7..f3e440b4cb 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts @@ -21,16 +21,15 @@ export const meta = { items: { type: 'array', optional: false, nullable: false, - items: { - anyOf: [ - { - type: 'string', - }, - { - type: 'number', - }, - ], - }, + prefixItems: [ + { + type: 'string', + }, + { + type: 'number', + }, + ], + unevaluatedItems: false, }, example: [[ 'example.com', diff --git a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts index 305ae1af1d..e7589cba81 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts @@ -21,16 +21,15 @@ export const meta = { items: { type: 'array', optional: false, nullable: false, - items: { - anyOf: [ - { - type: 'string', - }, - { - type: 'number', - }, - ], - }, + prefixItems: [ + { + type: 'string', + }, + { + type: 'number', + }, + ], + unevaluatedItems: false, }, example: [[ 'example.com', diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index 9b79100fcf..554d324ff2 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -32,7 +32,7 @@ export const paramDef = { type: 'object', properties: { reportId: { type: 'string', format: 'misskey:id' }, - forward: { type: 'boolean', default: false }, + resolvedAs: { type: 'string', enum: ['accept', 'reject', null], nullable: true }, }, required: ['reportId'], } as const; @@ -50,7 +50,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchAbuseReport); } - await this.abuseReportService.resolve([{ reportId: report.id, forward: ps.forward }], me); + await this.abuseReportService.resolve([{ reportId: report.id, resolvedAs: ps.resolvedAs ?? null }], me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update-default-policies.ts b/packages/backend/src/server/api/endpoints/admin/roles/update-default-policies.ts index d7209965db..5cf49670be 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/update-default-policies.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/update-default-policies.ts @@ -7,6 +7,7 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { MetaService } from '@/core/MetaService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin', 'role'], @@ -33,12 +34,22 @@ export default class extends Endpoint { // eslint- constructor( private metaService: MetaService, private globalEventService: GlobalEventService, + private moderationLogService: ModerationLogService, ) { - super(meta, paramDef, async (ps) => { + super(meta, paramDef, async (ps, me) => { + const before = await this.metaService.fetch(true); + await this.metaService.update({ policies: ps.policies, }); - this.globalEventService.publishInternalEvent('policiesUpdated', ps.policies); + + const after = await this.metaService.fetch(true); + + this.globalEventService.publishInternalEvent('policiesUpdated', after.policies); + this.moderationLogService.log(me, 'updateServerSettings', { + before: before.policies, + after: after.policies, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 5a1c05f41a..655bd32bce 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -31,6 +31,10 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, + followedMessage: { + type: 'string', + optional: false, nullable: true, + }, autoAcceptFollowed: { type: 'boolean', optional: false, nullable: false, @@ -226,6 +230,7 @@ export default class extends Endpoint { // eslint- return { email: profile.email, emailVerified: profile.emailVerified, + followedMessage: profile.followedMessage, autoAcceptFollowed: profile.autoAcceptFollowed, noCrawle: profile.noCrawle, preventAiLearning: profile.preventAiLearning, diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 2fef9abbf9..2b2c8c60ab 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -71,13 +71,13 @@ export default class extends Endpoint { // eslint- break; } case 'moderator': { - const moderatorIds = await this.roleService.getModeratorIds(false); + const moderatorIds = await this.roleService.getModeratorIds({ includeAdmins: false }); if (moderatorIds.length === 0) return []; query.where('user.id IN (:...moderatorIds)', { moderatorIds: moderatorIds }); break; } case 'adminOrModerator': { - const adminOrModeratorIds = await this.roleService.getModeratorIds(); + const adminOrModeratorIds = await this.roleService.getModeratorIds({ includeAdmins: true }); if (adminOrModeratorIds.length === 0) return []; query.where('user.id IN (:...adminOrModeratorIds)', { adminOrModeratorIds: adminOrModeratorIds }); break; diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts index 8a946405cc..bea1bdc4ed 100644 --- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts @@ -3,18 +3,12 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { IsNull, Not } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, FollowingsRepository } from '@/models/_.js'; -import type { MiUser } from '@/models/User.js'; -import type { RelationshipJobData } from '@/queue/types.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; +import type { UsersRepository } from '@/models/_.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; -import { QueueService } from '@/core/QueueService.js'; export const meta = { tags: ['admin'], @@ -38,13 +32,8 @@ export default class extends Endpoint { // eslint- @Inject(DI.usersRepository) private usersRepository: UsersRepository, - @Inject(DI.followingsRepository) - private followingsRepository: FollowingsRepository, - private userSuspendService: UserSuspendService, private roleService: RoleService, - private moderationLogService: ModerationLogService, - private queueService: QueueService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy({ id: ps.userId }); @@ -57,42 +46,7 @@ export default class extends Endpoint { // eslint- throw new Error('cannot suspend moderator account'); } - await this.usersRepository.update(user.id, { - isSuspended: true, - }); - - this.moderationLogService.log(me, 'suspend', { - userId: user.id, - userUsername: user.username, - userHost: user.host, - }); - - (async () => { - await this.userSuspendService.doPostSuspend(user).catch(e => {}); - await this.unFollowAll(user).catch(e => {}); - })(); + await this.userSuspendService.suspend(user, me); }); } - - @bindThis - private async unFollowAll(follower: MiUser) { - const followings = await this.followingsRepository.find({ - where: { - followerId: follower.id, - followeeId: Not(IsNull()), - }, - }); - - const jobs: RelationshipJobData[] = []; - for (const following of followings) { - if (following.followeeId && following.followerId) { - jobs.push({ - from: { id: following.followerId }, - to: { id: following.followeeId }, - silent: true, - }); - } - } - this.queueService.createUnfollowJob(jobs); - } } diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/test.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/test.ts new file mode 100644 index 0000000000..fb2ddf4b44 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/test.ts @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import ms from 'ms'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { WebhookTestService } from '@/core/WebhookTestService.js'; +import { ApiError } from '@/server/api/error.js'; +import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; + +export const meta = { + tags: ['webhooks'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'read:admin:system-webhook', + + limit: { + duration: ms('15min'), + max: 60, + }, + + errors: { + noSuchWebhook: { + message: 'No such webhook.', + code: 'NO_SUCH_WEBHOOK', + id: '0c52149c-e913-18f8-5dc7-74870bfe0cf9', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + webhookId: { + type: 'string', + format: 'misskey:id', + }, + type: { + type: 'string', + enum: systemWebhookEventTypes, + }, + override: { + type: 'object', + properties: { + url: { type: 'string', nullable: false }, + secret: { type: 'string', nullable: false }, + }, + }, + }, + required: ['webhookId', 'type'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private webhookTestService: WebhookTestService, + ) { + super(meta, paramDef, async (ps) => { + try { + await this.webhookTestService.testSystemWebhook({ + webhookId: ps.webhookId, + type: ps.type, + override: ps.override, + }); + } catch (e) { + if (e instanceof WebhookTestService.NoSuchWebhookError) { + throw new ApiError(meta.errors.noSuchWebhook); + } + throw e; + } + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts index 2c2b1bf6f5..b52c638cdb 100644 --- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts @@ -6,7 +6,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository } from '@/models/_.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; @@ -33,7 +32,6 @@ export default class extends Endpoint { // eslint- private usersRepository: UsersRepository, private userSuspendService: UserSuspendService, - private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy({ id: ps.userId }); @@ -42,17 +40,7 @@ export default class extends Endpoint { // eslint- throw new Error('user not found'); } - await this.usersRepository.update(user.id, { - isSuspended: false, - }); - - this.moderationLogService.log(me, 'unsuspend', { - userId: user.id, - userUsername: user.username, - userHost: user.host, - }); - - this.userSuspendService.doPostUnsuspend(user); + await this.userSuspendService.unsuspend(user, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/update-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/update-abuse-user-report.ts new file mode 100644 index 0000000000..73d4b843f0 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/update-abuse-user-report.ts @@ -0,0 +1,58 @@ +/* + * 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 type { AbuseUserReportsRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '@/server/api/error.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + kind: 'write:admin:resolve-abuse-user-report', + + errors: { + noSuchAbuseReport: { + message: 'No such abuse report.', + code: 'NO_SUCH_ABUSE_REPORT', + id: '15f51cf5-46d1-4b1d-a618-b35bcbed0662', + kind: 'server', + httpStatusCode: 404, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + reportId: { type: 'string', format: 'misskey:id' }, + moderationNote: { type: 'string' }, + }, + required: ['reportId'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.abuseUserReportsRepository) + private abuseUserReportsRepository: AbuseUserReportsRepository, + private abuseReportService: AbuseReportService, + ) { + super(meta, paramDef, async (ps, me) => { + const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId }); + if (!report) { + throw new ApiError(meta.errors.noSuchAbuseReport); + } + + await this.abuseReportService.update(report.id, { + moderationNote: ps.moderationNote, + }, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 4e28ee6877..e97ac4e2b9 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -78,6 +78,7 @@ export const paramDef = { enableTurnstile: { type: 'boolean' }, turnstileSiteKey: { type: 'string', nullable: true }, turnstileSecretKey: { type: 'string', nullable: true }, + enableTestcaptcha: { type: 'boolean' }, sensitiveMediaDetection: { type: 'string', enum: ['none', 'all', 'local', 'remote'] }, sensitiveMediaDetectionSensitivity: { type: 'string', enum: ['medium', 'low', 'high', 'veryLow', 'veryHigh'] }, setSensitiveFlagAutomatically: { type: 'boolean' }, @@ -142,6 +143,7 @@ export const paramDef = { perRemoteUserUserTimelineCacheMax: { type: 'integer' }, perUserHomeTimelineCacheMax: { type: 'integer' }, perUserListTimelineCacheMax: { type: 'integer' }, + enableReactionsBuffering: { type: 'boolean' }, notesPerOneAd: { type: 'integer' }, silencedHosts: { type: 'array', @@ -150,6 +152,13 @@ export const paramDef = { type: 'string', }, }, + mediaSilencedHosts: { + type: 'array', + nullable: true, + items: { + type: 'string', + }, + }, summalyProxy: { type: 'string', nullable: true, description: '[Deprecated] Use "urlPreviewSummaryProxyUrl" instead.', @@ -160,6 +169,16 @@ export const paramDef = { urlPreviewRequireContentLength: { type: 'boolean' }, urlPreviewUserAgent: { type: 'string', nullable: true }, urlPreviewSummaryProxyUrl: { type: 'string', nullable: true }, + federation: { + type: 'string', + enum: ['all', 'none', 'specified'], + }, + federationHosts: { + type: 'array', + items: { + type: 'string', + }, + }, }, required: [], } as const; @@ -203,6 +222,14 @@ export default class extends Endpoint { // eslint- return h !== '' && h !== lv && !set.blockedHosts?.includes(h); }); } + if (Array.isArray(ps.mediaSilencedHosts)) { + let lastValue = ''; + set.mediaSilencedHosts = ps.mediaSilencedHosts.sort().filter((h) => { + const lv = lastValue; + lastValue = h; + return h !== '' && h !== lv && !set.blockedHosts?.includes(h); + }); + } if (ps.themeColor !== undefined) { set.themeColor = ps.themeColor; } @@ -331,6 +358,10 @@ export default class extends Endpoint { // eslint- set.turnstileSecretKey = ps.turnstileSecretKey; } + if (ps.enableTestcaptcha !== undefined) { + set.enableTestcaptcha = ps.enableTestcaptcha; + } + if (ps.sensitiveMediaDetection !== undefined) { set.sensitiveMediaDetection = ps.sensitiveMediaDetection; } @@ -583,6 +614,10 @@ export default class extends Endpoint { // eslint- set.perUserListTimelineCacheMax = ps.perUserListTimelineCacheMax; } + if (ps.enableReactionsBuffering !== undefined) { + set.enableReactionsBuffering = ps.enableReactionsBuffering; + } + if (ps.notesPerOneAd !== undefined) { set.notesPerOneAd = ps.notesPerOneAd; } @@ -617,6 +652,14 @@ export default class extends Endpoint { // eslint- set.urlPreviewSummaryProxyUrl = value === '' ? null : value; } + if (ps.federation !== undefined) { + set.federation = ps.federation; + } + + if (Array.isArray(ps.federationHosts)) { + set.federationHosts = ps.federationHosts.filter(Boolean).map(x => x.toLowerCase()); + } + const before = await this.metaService.fetch(true); await this.metaService.update(set); diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index 577b9e1b1f..e0c8ddcc84 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -34,6 +34,12 @@ export const meta = { code: 'TOO_MANY_ANTENNAS', id: 'faf47050-e8b5-438c-913c-db2b1576fde4', }, + + emptyKeyword: { + message: 'Either keywords or excludeKeywords is required.', + code: 'EMPTY_KEYWORD', + id: '53ee222e-1ddd-4f9a-92e5-9fb82ddb463a', + }, }, res: { @@ -87,7 +93,7 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { if (ps.keywords.flat().every(x => x === '') && ps.excludeKeywords.flat().every(x => x === '')) { - throw new Error('either keywords or excludeKeywords is required.'); + throw new ApiError(meta.errors.emptyKeyword); } const currentAntennasCount = await this.antennasRepository.countBy({ diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts index 0c30bca9e0..10f26b1912 100644 --- a/packages/backend/src/server/api/endpoints/antennas/update.ts +++ b/packages/backend/src/server/api/endpoints/antennas/update.ts @@ -32,6 +32,12 @@ export const meta = { code: 'NO_SUCH_USER_LIST', id: '1c6b35c9-943e-48c2-81e4-2844989407f7', }, + + emptyKeyword: { + message: 'Either keywords or excludeKeywords is required.', + code: 'EMPTY_KEYWORD', + id: '721aaff6-4e1b-4d88-8de6-877fae9f68c4', + }, }, res: { @@ -85,7 +91,7 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { if (ps.keywords && ps.excludeKeywords) { if (ps.keywords.flat().every(x => x === '') && ps.excludeKeywords.flat().every(x => x === '')) { - throw new Error('either keywords or excludeKeywords is required.'); + throw new ApiError(meta.errors.emptyKeyword); } } // Fetch the antenna diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index d3c40dba59..c52608cefb 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { MiNote } from '@/models/Note.js'; @@ -12,7 +12,6 @@ import { isActor, isPost, getApId } from '@/core/activitypub/type.js'; import type { SchemaType } from '@/misc/json-schema.js'; import { ApResolverService } from '@/core/activitypub/ApResolverService.js'; import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js'; -import { MetaService } from '@/core/MetaService.js'; import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; import { ApNoteService } from '@/core/activitypub/models/ApNoteService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -91,7 +90,6 @@ export default class extends Endpoint { // eslint- private utilityService: UtilityService, private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, - private metaService: MetaService, private apResolverService: ApResolverService, private apDbResolverService: ApDbResolverService, private apPersonService: ApPersonService, @@ -112,9 +110,7 @@ export default class extends Endpoint { // eslint- */ @bindThis private async fetchAny(uri: string, me: MiLocalUser | null | undefined): Promise | null> { - // ブロックしてたら中断 - const fetchedMeta = await this.metaService.fetch(); - if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null; + if (!this.utilityService.isFederationAllowedUri(uri)) return null; let local = await this.mergePack(me, ...await Promise.all([ this.apDbResolverService.getUserFromApId(uri), diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index 8c55673590..d4fd75e049 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -5,14 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository, NotesRepository } from '@/models/_.js'; +import type { ChannelsRepository, MiMeta, NotesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; -import { CacheService } from '@/core/CacheService.js'; -import { MetaService } from '@/core/MetaService.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { MiLocalUser } from '@/models/User.js'; import { ApiError } from '../../error.js'; @@ -58,6 +56,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -68,16 +69,12 @@ export default class extends Endpoint { // eslint- private noteEntityService: NoteEntityService, private queryService: QueryService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, - private cacheService: CacheService, private activeUsersChart: ActiveUsersChart, - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null); - const serverSettings = await this.metaService.fetch(); - const channel = await this.channelsRepository.findOneBy({ id: ps.channelId, }); @@ -88,7 +85,7 @@ export default class extends Endpoint { // eslint- if (me) this.activeUsersChart.read(me); - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { return await this.noteEntityService.packMany(await this.getFromDb({ untilId, sinceId, limit: ps.limit, channelId: channel.id }, me), me); } diff --git a/packages/backend/src/server/api/endpoints/drive.ts b/packages/backend/src/server/api/endpoints/drive.ts index 7e9b0fa0e1..eb45e29f9e 100644 --- a/packages/backend/src/server/api/endpoints/drive.ts +++ b/packages/backend/src/server/api/endpoints/drive.ts @@ -5,7 +5,6 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { MetaService } from '@/core/MetaService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { RoleService } from '@/core/RoleService.js'; @@ -41,14 +40,10 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - private metaService: MetaService, private driveFileEntityService: DriveFileEntityService, private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { - const instance = await this.metaService.fetch(true); - - // Calculate drive usage const usage = await this.driveFileEntityService.calcDriveUsageOf(me.id); const policies = await this.roleService.getUserPolicies(me.id); diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 4670392025..b86059b5e7 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -10,6 +10,7 @@ import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['drive', 'notes'], @@ -61,12 +62,13 @@ export default class extends Endpoint { // eslint- private noteEntityService: NoteEntityService, private queryService: QueryService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { // Fetch file const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId, - userId: me.id, + userId: await this.roleService.isModerator(me) ? undefined : me.id, }); if (file == null) { diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 9c17f93ab2..74eb4dded7 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -4,14 +4,15 @@ */ import ms from 'ms'; -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/const.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; -import { MetaService } from '@/core/MetaService.js'; import { DriveService } from '@/core/DriveService.js'; import { ApiError } from '../../../error.js'; +import { MiMeta } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; export const meta = { tags: ['drive'], @@ -73,8 +74,10 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + private driveFileEntityService: DriveFileEntityService, - private metaService: MetaService, private driveService: DriveService, ) { super(meta, paramDef, async (ps, me, _, file, cleanup, ip, headers) => { @@ -91,8 +94,6 @@ export default class extends Endpoint { // eslint- } } - const instance = await this.metaService.fetch(); - try { // Create file const driveFile = await this.driveService.addFile({ @@ -103,8 +104,8 @@ export default class extends Endpoint { // eslint- folderId: ps.folderId, force: ps.force, sensitive: ps.isSensitive, - requestIp: instance.enableIpLogging ? ip : null, - requestHeaders: instance.enableIpLogging ? headers : null, + requestIp: this.serverSettings.enableIpLogging ? ip : null, + requestHeaders: this.serverSettings.enableIpLogging ? headers : null, }); return await this.driveFileEntityService.pack(driveFile, { self: true }); } catch (err) { diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 36f4bf5aa6..41954129e6 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -170,7 +170,7 @@ export default class extends Endpoint { // eslint- const instances = await query.limit(ps.limit).offset(ps.offset).getMany(); - return await this.instanceEntityService.packMany(instances); + return await this.instanceEntityService.packMany(instances, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/federation/stats.ts b/packages/backend/src/server/api/endpoints/federation/stats.ts index bac54970ab..69900bff9a 100644 --- a/packages/backend/src/server/api/endpoints/federation/stats.ts +++ b/packages/backend/src/server/api/endpoints/federation/stats.ts @@ -107,9 +107,9 @@ export default class extends Endpoint { // eslint- const gotPubCount = topPubInstances.map(x => x.followingCount).reduce((a, b) => a + b, 0); return await awaitAll({ - topSubInstances: this.instanceEntityService.packMany(topSubInstances), + topSubInstances: this.instanceEntityService.packMany(topSubInstances, me), otherFollowersCount: Math.max(0, allSubCount - gotSubCount), - topPubInstances: this.instanceEntityService.packMany(topPubInstances), + topPubInstances: this.instanceEntityService.packMany(topPubInstances, me), otherFollowingCount: Math.max(0, allPubCount - gotPubCount), }); }); diff --git a/packages/backend/src/server/api/endpoints/flash/delete.ts b/packages/backend/src/server/api/endpoints/flash/delete.ts index d3d47e5deb..6912450abf 100644 --- a/packages/backend/src/server/api/endpoints/flash/delete.ts +++ b/packages/backend/src/server/api/endpoints/flash/delete.ts @@ -4,9 +4,11 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/_.js'; +import type { FlashsRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -44,17 +46,35 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.flashsRepository) private flashsRepository: FlashsRepository, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + private moderationLogService: ModerationLogService, + private roleService: RoleService, ) { 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) { + + if (!await this.roleService.isModerator(me) && flash.userId !== me.id) { throw new ApiError(meta.errors.accessDenied); } await this.flashsRepository.delete(flash.id); + + if (flash.userId !== me.id) { + const user = await this.usersRepository.findOneByOrFail({ id: flash.userId }); + this.moderationLogService.log(me, 'deleteFlash', { + flashId: flash.id, + flashUserId: flash.userId, + flashUserUsername: user.username, + flash, + }); + } }); } } diff --git a/packages/backend/src/server/api/endpoints/flash/featured.ts b/packages/backend/src/server/api/endpoints/flash/featured.ts index c2d6ab5085..9a0cb461f2 100644 --- a/packages/backend/src/server/api/endpoints/flash/featured.ts +++ b/packages/backend/src/server/api/endpoints/flash/featured.ts @@ -8,6 +8,7 @@ import type { FlashsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { DI } from '@/di-symbols.js'; +import { FlashService } from '@/core/FlashService.js'; export const meta = { tags: ['flash'], @@ -27,26 +28,25 @@ export const meta = { export const paramDef = { type: 'object', - properties: {}, + properties: { + offset: { type: 'integer', minimum: 0, default: 0 }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, required: [], } as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.flashsRepository) - private flashsRepository: FlashsRepository, - + private flashService: FlashService, 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.limit(10).getMany(); - - return await this.flashEntityService.packMany(flashs, me); + const result = await this.flashService.featured({ + offset: ps.offset, + limit: ps.limit, + }); + return await this.flashEntityService.packMany(result, me); }); } } 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 527e3fb52d..b6b94db161 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts @@ -5,8 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/_.js'; +import type { GalleryPostsRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -22,6 +24,12 @@ export const meta = { code: 'NO_SUCH_POST', id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5', }, + + accessDenied: { + message: 'Access denied.', + code: 'ACCESS_DENIED', + id: 'c86e09de-1c48-43ac-a435-1c7e42ed4496', + }, }, } as const; @@ -38,18 +46,35 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.galleryPostsRepository) private galleryPostsRepository: GalleryPostsRepository, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + private moderationLogService: ModerationLogService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { - const post = await this.galleryPostsRepository.findOneBy({ - id: ps.postId, - userId: me.id, - }); + const post = await this.galleryPostsRepository.findOneBy({ id: ps.postId }); if (post == null) { throw new ApiError(meta.errors.noSuchPost); } + if (!await this.roleService.isModerator(me) && post.userId !== me.id) { + throw new ApiError(meta.errors.accessDenied); + } + await this.galleryPostsRepository.delete(post.id); + + if (post.userId !== me.id) { + const user = await this.usersRepository.findOneByOrFail({ id: post.userId }); + this.moderationLogService.log(me, 'deleteGalleryPost', { + postId: post.id, + postUserId: post.userId, + postUserUsername: user.username, + post, + }); + } }); } } diff --git a/packages/backend/src/server/api/endpoints/i/import-antennas.ts b/packages/backend/src/server/api/endpoints/i/import-antennas.ts index bc46163e3d..bdf6c065e8 100644 --- a/packages/backend/src/server/api/endpoints/i/import-antennas.ts +++ b/packages/backend/src/server/api/endpoints/i/import-antennas.ts @@ -16,6 +16,7 @@ import { ApiError } from '../../error.js'; export const meta = { secure: true, requireCredential: true, + requireRolePolicy: 'canImportAntennas', prohibitMoved: true, limit: { diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index 2606108539..d7bb6bcd22 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -15,6 +15,7 @@ import { ApiError } from '../../error.js'; export const meta = { secure: true, requireCredential: true, + requireRolePolicy: 'canImportBlocking', prohibitMoved: true, limit: { diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index d5e824df27..e03192d8c6 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -15,6 +15,7 @@ import { ApiError } from '../../error.js'; export const meta = { secure: true, requireCredential: true, + requireRolePolicy: 'canImportFollowing', prohibitMoved: true, limit: { duration: ms('1hour'), diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index 0f5800404e..76b285bb7e 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -15,6 +15,7 @@ import { ApiError } from '../../error.js'; export const meta = { secure: true, requireCredential: true, + requireRolePolicy: 'canImportMuting', prohibitMoved: true, limit: { diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index bacdd5c88f..76ecfd082c 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -15,6 +15,7 @@ import { ApiError } from '../../error.js'; export const meta = { secure: true, requireCredential: true, + requireRolePolicy: 'canImportUserLists', prohibitMoved: true, limit: { duration: ms('1hour'), diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index eea657ebbd..da1faee30d 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import bcrypt from 'bcryptjs'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository } from '@/models/_.js'; +import type { MiMeta, UserProfilesRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { EmailService } from '@/core/EmailService.js'; import type { Config } from '@/config.js'; @@ -15,7 +15,6 @@ import { DI } from '@/di-symbols.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js'; import { UserAuthService } from '@/core/UserAuthService.js'; -import { MetaService } from '@/core/MetaService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -70,10 +69,12 @@ export default class extends Endpoint { // eslint- @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, - private metaService: MetaService, private userEntityService: UserEntityService, private emailService: EmailService, private userAuthService: UserAuthService, @@ -105,7 +106,7 @@ export default class extends Endpoint { // eslint- if (!res.available) { throw new ApiError(meta.errors.unavailable); } - } else if ((await this.metaService.fetch()).emailRequiredForSignup) { + } else if (this.serverSettings.emailRequiredForSignup) { throw new ApiError(meta.errors.emailRequired); } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index a8e702f328..798bd98cf1 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -13,9 +13,8 @@ import { extractHashtags } from '@/misc/extract-hashtags.js'; import * as Acct from '@/misc/acct.js'; import type { UsersRepository, DriveFilesRepository, UserProfilesRepository, PagesRepository } from '@/models/_.js'; import type { MiLocalUser, MiUser } from '@/models/User.js'; -import { birthdaySchema, descriptionSchema, locationSchema, nameSchema } from '@/models/User.js'; +import { birthdaySchema, descriptionSchema, followedMessageSchema, locationSchema, nameSchema } from '@/models/User.js'; import type { MiUserProfile } from '@/models/UserProfile.js'; -import { notificationTypes } from '@/types.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { langmap } from '@/misc/langmap.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -25,7 +24,7 @@ import { UserFollowingService } from '@/core/UserFollowingService.js'; import { AccountUpdateService } from '@/core/AccountUpdateService.js'; import { HashtagService } from '@/core/HashtagService.js'; import { DI } from '@/di-symbols.js'; -import { RoleService } from '@/core/RoleService.js'; +import { RolePolicies, RoleService } from '@/core/RoleService.js'; import { CacheService } from '@/core/CacheService.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; @@ -134,6 +133,7 @@ export const paramDef = { properties: { name: { ...nameSchema, nullable: true }, description: { ...descriptionSchema, nullable: true }, + followedMessage: { ...followedMessageSchema, nullable: true }, location: { ...locationSchema, nullable: true }, birthday: { ...birthdaySchema, nullable: true }, lang: { type: 'string', enum: [null, ...Object.keys(langmap)] as string[], nullable: true }, @@ -256,9 +256,18 @@ export default class extends Endpoint { // eslint- const profileUpdates = {} as Partial; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); + let policies: RolePolicies | null = null; - if (ps.name !== undefined) updates.name = ps.name; + if (ps.name !== undefined) { + if (ps.name === null) { + updates.name = null; + } else { + const trimmedName = ps.name.trim(); + updates.name = trimmedName === '' ? null : trimmedName; + } + } if (ps.description !== undefined) profileUpdates.description = ps.description; + if (ps.followedMessage !== undefined) profileUpdates.followedMessage = ps.followedMessage; if (ps.lang !== undefined) profileUpdates.lang = ps.lang; if (ps.location !== undefined) profileUpdates.location = ps.location; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; @@ -289,14 +298,16 @@ export default class extends Endpoint { // eslint- } if (ps.mutedWords !== undefined) { - checkMuteWordCount(ps.mutedWords, (await this.roleService.getUserPolicies(user.id)).wordMuteLimit); + policies ??= await this.roleService.getUserPolicies(user.id); + checkMuteWordCount(ps.mutedWords, policies.wordMuteLimit); validateMuteWordRegex(ps.mutedWords); profileUpdates.mutedWords = ps.mutedWords; profileUpdates.enableWordMute = ps.mutedWords.length > 0; } if (ps.hardMutedWords !== undefined) { - checkMuteWordCount(ps.hardMutedWords, (await this.roleService.getUserPolicies(user.id)).wordMuteLimit); + policies ??= await this.roleService.getUserPolicies(user.id); + checkMuteWordCount(ps.hardMutedWords, policies.wordMuteLimit); validateMuteWordRegex(ps.hardMutedWords); profileUpdates.hardMutedWords = ps.hardMutedWords; } @@ -315,13 +326,17 @@ export default class extends Endpoint { // eslint- if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote; if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail; if (typeof ps.alwaysMarkNsfw === 'boolean') { - if ((await roleService.getUserPolicies(user.id)).alwaysMarkNsfw) throw new ApiError(meta.errors.restrictedByRole); + policies ??= await this.roleService.getUserPolicies(user.id); + if (policies.alwaysMarkNsfw) throw new ApiError(meta.errors.restrictedByRole); profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw; } if (typeof ps.autoSensitive === 'boolean') profileUpdates.autoSensitive = ps.autoSensitive; if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes; if (ps.avatarId) { + policies ??= await this.roleService.getUserPolicies(user.id); + if (!policies.canUpdateBioMedia) throw new ApiError(meta.errors.restrictedByRole); + const avatar = await this.driveFilesRepository.findOneBy({ id: ps.avatarId }); if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar); @@ -337,6 +352,9 @@ export default class extends Endpoint { // eslint- } if (ps.bannerId) { + policies ??= await this.roleService.getUserPolicies(user.id); + if (!policies.canUpdateBioMedia) throw new ApiError(meta.errors.restrictedByRole); + const banner = await this.driveFilesRepository.findOneBy({ id: ps.bannerId }); if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner); @@ -352,14 +370,15 @@ export default class extends Endpoint { // eslint- } if (ps.avatarDecorations) { + policies ??= await this.roleService.getUserPolicies(user.id); const decorations = await this.avatarDecorationService.getAll(true); - const [myRoles, myPolicies] = await Promise.all([this.roleService.getUserRoles(user.id), this.roleService.getUserPolicies(user.id)]); + const myRoles = await this.roleService.getUserRoles(user.id); const allRoles = await this.roleService.getRoles(); const decorationIds = decorations .filter(d => d.roleIdsThatCanBeUsedThisDecoration.filter(roleId => allRoles.some(r => r.id === roleId)).length === 0 || myRoles.some(r => d.roleIdsThatCanBeUsedThisDecoration.includes(r.id))) .map(d => d.id); - if (ps.avatarDecorations.length > myPolicies.avatarDecorationLimit) throw new ApiError(meta.errors.restrictedByRole); + if (ps.avatarDecorations.length > policies.avatarDecorationLimit) throw new ApiError(meta.errors.restrictedByRole); updates.avatarDecorations = ps.avatarDecorations.filter(d => decorationIds.includes(d.id)).map(d => ({ id: d.id, diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts index 9eb7f5b3a0..6e84603f7a 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts @@ -13,6 +13,7 @@ import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '@/server/api/error.js'; +// TODO: UserWebhook schemaの適用 export const meta = { tags: ['webhooks'], diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts index fe07afb2d0..394c178f2a 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts @@ -9,6 +9,7 @@ import { webhookEventTypes } from '@/models/Webhook.js'; import type { WebhooksRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +// TODO: UserWebhook schemaの適用 export const meta = { tags: ['webhooks', 'account'], diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts index 5ddb79caf2..4a0c09ff0c 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts @@ -10,6 +10,7 @@ import type { WebhooksRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; +// TODO: UserWebhook schemaの適用 export const meta = { tags: ['webhooks'], diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/test.ts b/packages/backend/src/server/api/endpoints/i/webhooks/test.ts new file mode 100644 index 0000000000..2bf6df9ce2 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/i/webhooks/test.ts @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import ms from 'ms'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { webhookEventTypes } from '@/models/Webhook.js'; +import { WebhookTestService } from '@/core/WebhookTestService.js'; +import { ApiError } from '@/server/api/error.js'; + +export const meta = { + tags: ['webhooks'], + + requireCredential: true, + secure: true, + kind: 'read:account', + + limit: { + duration: ms('15min'), + max: 60, + }, + + errors: { + noSuchWebhook: { + message: 'No such webhook.', + code: 'NO_SUCH_WEBHOOK', + id: '0c52149c-e913-18f8-5dc7-74870bfe0cf9', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + webhookId: { + type: 'string', + format: 'misskey:id', + }, + type: { + type: 'string', + enum: webhookEventTypes, + }, + override: { + type: 'object', + properties: { + url: { type: 'string' }, + secret: { type: 'string' }, + }, + }, + }, + required: ['webhookId', 'type'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private webhookTestService: WebhookTestService, + ) { + super(meta, paramDef, async (ps, me) => { + try { + await this.webhookTestService.testUserWebhook({ + webhookId: ps.webhookId, + type: ps.type, + override: ps.override, + }, me); + } catch (e) { + if (e instanceof WebhookTestService.NoSuchWebhookError) { + throw new ApiError(meta.errors.noSuchWebhook); + } + throw e; + } + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index beb77ca7ab..253a360815 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -17,8 +17,6 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteCreateService } from '@/core/NoteCreateService.js'; import { DI } from '@/di-symbols.js'; import { isQuote, isRenote } from '@/misc/is-renote.js'; -import { MetaService } from '@/core/MetaService.js'; -import { UtilityService } from '@/core/UtilityService.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index 5acc9706d3..aed9065bf9 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, ChannelFollowingsRepository } from '@/models/_.js'; +import type { NotesRepository, ChannelFollowingsRepository, MiMeta } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; @@ -16,7 +16,6 @@ import { CacheService } from '@/core/CacheService.js'; import { FanoutTimelineName } from '@/core/FanoutTimelineService.js'; import { QueryService } from '@/core/QueryService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; -import { MetaService } from '@/core/MetaService.js'; import { MiLocalUser } from '@/models/User.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { ApiError } from '../../error.js'; @@ -74,6 +73,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -87,7 +89,6 @@ export default class extends Endpoint { // eslint- private cacheService: CacheService, private queryService: QueryService, private userFollowingService: UserFollowingService, - private metaService: MetaService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, ) { super(meta, paramDef, async (ps, me) => { @@ -101,9 +102,7 @@ export default class extends Endpoint { // eslint- if (ps.withReplies && ps.withFiles) throw new ApiError(meta.errors.bothWithRepliesAndWithFiles); - const serverSettings = await this.metaService.fetch(); - - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { const timeline = await this.getFromDb({ untilId, sinceId, @@ -139,9 +138,16 @@ export default class extends Endpoint { // eslint- timelineConfig = [ `homeTimeline:${me.id}`, 'localTimeline', + `localTimelineWithReplyTo:${me.id}`, ]; } + const [ + followings, + ] = await Promise.all([ + this.cacheService.userFollowingsCache.fetch(me.id), + ]); + const redisTimeline = await this.fanoutTimelineEndpointService.timeline({ untilId, sinceId, @@ -149,9 +155,16 @@ export default class extends Endpoint { // eslint- allowPartial: ps.allowPartial, me, redisTimelines: timelineConfig, - useDbFallback: serverSettings.enableFanoutTimelineDbFallback, + useDbFallback: this.serverSettings.enableFanoutTimelineDbFallback, alwaysIncludeMyNotes: true, excludePureRenotes: !ps.withRenotes, + noteFilter: note => { + if (note.reply && note.reply.visibility === 'followers') { + if (!Object.hasOwn(followings, note.reply.userId) && note.reply.userId !== me.id) return false; + } + + return true; + }, dbFallback: async (untilId, sinceId, limit) => await this.getFromDb({ untilId, sinceId, diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index be82b5a8a7..0b48f2c78b 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -5,16 +5,14 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/_.js'; +import type { MiMeta, NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; import { IdService } from '@/core/IdService.js'; -import { CacheService } from '@/core/CacheService.js'; import { QueryService } from '@/core/QueryService.js'; -import { MetaService } from '@/core/MetaService.js'; import { MiLocalUser } from '@/models/User.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { ApiError } from '../../error.js'; @@ -66,6 +64,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -73,10 +74,8 @@ export default class extends Endpoint { // eslint- private roleService: RoleService, private activeUsersChart: ActiveUsersChart, private idService: IdService, - private cacheService: CacheService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, private queryService: QueryService, - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); @@ -89,9 +88,7 @@ export default class extends Endpoint { // eslint- if (ps.withReplies && ps.withFiles) throw new ApiError(meta.errors.bothWithRepliesAndWithFiles); - const serverSettings = await this.metaService.fetch(); - - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { const timeline = await this.getFromDb({ untilId, sinceId, @@ -115,7 +112,7 @@ export default class extends Endpoint { // eslint- limit: ps.limit, allowPartial: ps.allowPartial, me, - useDbFallback: serverSettings.enableFanoutTimelineDbFallback, + useDbFallback: this.serverSettings.enableFanoutTimelineDbFallback, redisTimelines: ps.withFiles ? ['localTimelineWithFiles'] : ps.withReplies ? ['localTimeline', 'localTimelineWithReplies'] diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index 8b87908bd3..7cb11cc1eb 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, ChannelFollowingsRepository } from '@/models/_.js'; +import type { NotesRepository, ChannelFollowingsRepository, MiMeta } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; @@ -15,7 +15,6 @@ import { IdService } from '@/core/IdService.js'; import { CacheService } from '@/core/CacheService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; import { MiLocalUser } from '@/models/User.js'; -import { MetaService } from '@/core/MetaService.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; export const meta = { @@ -56,6 +55,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -69,15 +71,12 @@ export default class extends Endpoint { // eslint- private fanoutTimelineEndpointService: FanoutTimelineEndpointService, private userFollowingService: UserFollowingService, private queryService: QueryService, - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null); - const serverSettings = await this.metaService.fetch(); - - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { const timeline = await this.getFromDb({ untilId, sinceId, @@ -108,13 +107,13 @@ export default class extends Endpoint { // eslint- limit: ps.limit, allowPartial: ps.allowPartial, me, - useDbFallback: serverSettings.enableFanoutTimelineDbFallback, + useDbFallback: this.serverSettings.enableFanoutTimelineDbFallback, redisTimelines: ps.withFiles ? [`homeTimelineWithFiles:${me.id}`] : [`homeTimeline:${me.id}`], alwaysIncludeMyNotes: true, excludePureRenotes: !ps.withRenotes, noteFilter: note => { if (note.reply && note.reply.visibility === 'followers') { - if (!Object.hasOwn(followings, note.reply.userId)) return false; + if (!Object.hasOwn(followings, note.reply.userId) && note.reply.userId !== me.id) return false; } return true; diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index 38a9660aa2..e9a6a36b02 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -4,14 +4,15 @@ */ import { URLSearchParams } from 'node:url'; -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; -import { MetaService } from '@/core/MetaService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { GetterService } from '@/server/api/GetterService.js'; import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; +import { MiMeta } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; export const meta = { tags: ['notes'], @@ -59,9 +60,11 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + private noteEntityService: NoteEntityService, private getterService: GetterService, - private metaService: MetaService, private httpRequestService: HttpRequestService, private roleService: RoleService, ) { @@ -84,9 +87,7 @@ export default class extends Endpoint { // eslint- return; } - const instance = await this.metaService.fetch(); - - if (instance.deeplAuthKey == null) { + if (this.serverSettings.deeplAuthKey == null) { throw new ApiError(meta.errors.unavailable); } @@ -94,11 +95,11 @@ export default class extends Endpoint { // eslint- if (targetLang.includes('-')) targetLang = targetLang.split('-')[0]; const params = new URLSearchParams(); - params.append('auth_key', instance.deeplAuthKey); + params.append('auth_key', this.serverSettings.deeplAuthKey); params.append('text', note.text); params.append('target_lang', targetLang); - const endpoint = instance.deeplIsPro ? 'https://api.deepl.com/v2/translate' : 'https://api-free.deepl.com/v2/translate'; + const endpoint = this.serverSettings.deeplIsPro ? 'https://api.deepl.com/v2/translate' : 'https://api-free.deepl.com/v2/translate'; const res = await this.httpRequestService.send(endpoint, { method: 'POST', diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 43877e61ef..6c7185c9eb 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -5,16 +5,14 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; -import type { MiUserList, NotesRepository, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js'; +import type { MiMeta, MiUserList, NotesRepository, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { DI } from '@/di-symbols.js'; -import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; import { QueryService } from '@/core/QueryService.js'; import { MiLocalUser } from '@/models/User.js'; -import { MetaService } from '@/core/MetaService.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { ApiError } from '../../error.js'; @@ -69,6 +67,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -80,11 +81,9 @@ export default class extends Endpoint { // eslint- private noteEntityService: NoteEntityService, private activeUsersChart: ActiveUsersChart, - private cacheService: CacheService, private idService: IdService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, private queryService: QueryService, - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); @@ -99,9 +98,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchList); } - const serverSettings = await this.metaService.fetch(); - - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { const timeline = await this.getFromDb(list, { untilId, sinceId, @@ -124,7 +121,7 @@ export default class extends Endpoint { // eslint- limit: ps.limit, allowPartial: ps.allowPartial, me, - useDbFallback: serverSettings.enableFanoutTimelineDbFallback, + useDbFallback: this.serverSettings.enableFanoutTimelineDbFallback, redisTimelines: ps.withFiles ? [`userListTimelineWithFiles:${list.id}`] : [`userListTimeline:${list.id}`], alwaysIncludeMyNotes: true, excludePureRenotes: !ps.withRenotes, diff --git a/packages/backend/src/server/api/endpoints/pages/delete.ts b/packages/backend/src/server/api/endpoints/pages/delete.ts index aa2ba75a41..f2bc946788 100644 --- a/packages/backend/src/server/api/endpoints/pages/delete.ts +++ b/packages/backend/src/server/api/endpoints/pages/delete.ts @@ -4,9 +4,11 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository } from '@/models/_.js'; +import type { PagesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -44,17 +46,35 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.pagesRepository) private pagesRepository: PagesRepository, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + private moderationLogService: ModerationLogService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { const page = await this.pagesRepository.findOneBy({ id: ps.pageId }); + if (page == null) { throw new ApiError(meta.errors.noSuchPage); } - if (page.userId !== me.id) { + + if (!await this.roleService.isModerator(me) && page.userId !== me.id) { throw new ApiError(meta.errors.accessDenied); } await this.pagesRepository.delete(page.id); + + if (page.userId !== me.id) { + const user = await this.usersRepository.findOneByOrFail({ id: page.userId }); + this.moderationLogService.log(me, 'deletePage', { + pageId: page.id, + pageUserId: page.userId, + pageUserUsername: user.username, + page, + }); + } }); } } diff --git a/packages/backend/src/server/api/endpoints/pinned-users.ts b/packages/backend/src/server/api/endpoints/pinned-users.ts index 15832ef7f8..5b0b656c63 100644 --- a/packages/backend/src/server/api/endpoints/pinned-users.ts +++ b/packages/backend/src/server/api/endpoints/pinned-users.ts @@ -5,11 +5,10 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/_.js'; +import type { MiMeta, UsersRepository } from '@/models/_.js'; import * as Acct from '@/misc/acct.js'; import type { MiUser } from '@/models/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { MetaService } from '@/core/MetaService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; @@ -38,16 +37,16 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, - private metaService: MetaService, private userEntityService: UserEntityService, ) { super(meta, paramDef, async (ps, me) => { - const meta = await this.metaService.fetch(); - - const users = await Promise.all(meta.pinnedUsers.map(acct => Acct.parse(acct)).map(acct => this.usersRepository.findOneBy({ + const users = await Promise.all(this.serverSettings.pinnedUsers.map(acct => Acct.parse(acct)).map(acct => this.usersRepository.findOneBy({ usernameLower: acct.username.toLowerCase(), host: acct.host ?? IsNull(), }))); diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts index 39bf0cc428..84a1f010d4 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts @@ -6,12 +6,11 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { IdService } from '@/core/IdService.js'; -import type { RenoteMutingsRepository } from '@/models/_.js'; -import type { MiRenoteMuting } from '@/models/RenoteMuting.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; +import { UserRenoteMutingService } from "@/core/UserRenoteMutingService.js"; +import type { RenoteMutingsRepository } from '@/models/_.js'; export const meta = { tags: ['account'], @@ -62,7 +61,7 @@ export default class extends Endpoint { // eslint- private renoteMutingsRepository: RenoteMutingsRepository, private getterService: GetterService, - private idService: IdService, + private userRenoteMutingService: UserRenoteMutingService, ) { super(meta, paramDef, async (ps, me) => { const muter = me; @@ -79,21 +78,19 @@ export default class extends Endpoint { // eslint- }); // Check if already muting - const exist = await this.renoteMutingsRepository.findOneBy({ - muterId: muter.id, - muteeId: mutee.id, + const exist = await this.renoteMutingsRepository.exists({ + where: { + muterId: muter.id, + muteeId: mutee.id, + }, }); - if (exist != null) { + if (exist === true) { throw new ApiError(meta.errors.alreadyMuting); } // Create mute - await this.renoteMutingsRepository.insert({ - id: this.idService.gen(), - muterId: muter.id, - muteeId: mutee.id, - } as MiRenoteMuting); + await this.userRenoteMutingService.mute(muter, mutee); }); } } diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts index 6e037cc07e..1a584b8404 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts @@ -5,10 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RenoteMutingsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; +import { UserRenoteMutingService } from "@/core/UserRenoteMutingService.js"; +import type { RenoteMutingsRepository } from '@/models/_.js'; export const meta = { tags: ['account'], @@ -53,6 +54,7 @@ export default class extends Endpoint { // eslint- private renoteMutingsRepository: RenoteMutingsRepository, private getterService: GetterService, + private userRenoteMutingService: UserRenoteMutingService, ) { super(meta, paramDef, async (ps, me) => { const muter = me; @@ -79,9 +81,7 @@ export default class extends Endpoint { // eslint- } // Delete mute - await this.renoteMutingsRepository.delete({ - id: exist.id, - }); + await this.userRenoteMutingService.unmute([exist]); }); } } diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index c13802eb06..8301c85f2e 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -5,9 +5,10 @@ import * as os from 'node:os'; import si from 'systeminformation'; -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { MetaService } from '@/core/MetaService.js'; +import { MiMeta } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; export const meta = { requireCredential: false, @@ -73,10 +74,11 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - private metaService: MetaService, + @Inject(DI.meta) + private serverSettings: MiMeta, ) { super(meta, paramDef, async () => { - if (!(await this.metaService.fetch()).enableServerMachineStats) return { + if (!this.serverSettings.enableServerMachineStats) return { machine: '?', cpu: { model: '?', diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts index a9a33149f9..fd76df2d3c 100644 --- a/packages/backend/src/server/api/endpoints/sw/register.ts +++ b/packages/backend/src/server/api/endpoints/sw/register.ts @@ -5,9 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { IdService } from '@/core/IdService.js'; -import type { SwSubscriptionsRepository } from '@/models/_.js'; +import type { MiMeta, SwSubscriptionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { MetaService } from '@/core/MetaService.js'; import { DI } from '@/di-symbols.js'; import { PushNotificationService } from '@/core/PushNotificationService.js'; @@ -62,11 +61,13 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.swSubscriptionsRepository) private swSubscriptionsRepository: SwSubscriptionsRepository, private idService: IdService, - private metaService: MetaService, private pushNotificationService: PushNotificationService, ) { super(meta, paramDef, async (ps, me) => { @@ -78,12 +79,10 @@ export default class extends Endpoint { // eslint- publickey: ps.publickey, }); - const instance = await this.metaService.fetch(true); - if (exist != null) { return { state: 'already-subscribed' as const, - key: instance.swPublicKey, + key: this.serverSettings.swPublicKey, userId: me.id, endpoint: exist.endpoint, sendReadMessage: exist.sendReadMessage, @@ -103,7 +102,7 @@ export default class extends Endpoint { // eslint- return { state: 'subscribed' as const, - key: instance.swPublicKey, + key: this.serverSettings.swPublicKey, userId: me.id, endpoint: ps.endpoint, sendReadMessage: ps.sendReadMessage, diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts index affb0996f1..4944be9b05 100644 --- a/packages/backend/src/server/api/endpoints/username/available.ts +++ b/packages/backend/src/server/api/endpoints/username/available.ts @@ -5,11 +5,10 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; +import type { MiMeta, UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { localUsernameSchema } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; -import { MetaService } from '@/core/MetaService.js'; export const meta = { tags: ['users'], @@ -39,13 +38,14 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @Inject(DI.usedUsernamesRepository) private usedUsernamesRepository: UsedUsernamesRepository, - - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const exist = await this.usersRepository.countBy({ @@ -55,8 +55,7 @@ export default class extends Endpoint { // eslint- const exist2 = await this.usedUsernamesRepository.countBy({ username: ps.username.toLowerCase() }); - const meta = await this.metaService.fetch(); - const isPreserved = meta.preservedUsernames.map(x => x.toLowerCase()).includes(ps.username.toLowerCase()); + const isPreserved = this.serverSettings.preservedUsernames.map(x => x.toLowerCase()).includes(ps.username.toLowerCase()); return { available: exist === 0 && exist2 === 0 && !isPreserved, diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 7ce7734f53..a8b4319a61 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -11,6 +11,7 @@ import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -81,6 +82,7 @@ export default class extends Endpoint { // eslint- private utilityService: UtilityService, private followingEntityService: FollowingEntityService, private queryService: QueryService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy(ps.userId != null @@ -93,23 +95,25 @@ export default class extends Endpoint { // eslint- const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); - if (profile.followersVisibility === 'private') { - if (me == null || (me.id !== user.id)) { - throw new ApiError(meta.errors.forbidden); - } - } else if (profile.followersVisibility === 'followers') { - if (me == null) { - throw new ApiError(meta.errors.forbidden); - } else if (me.id !== user.id) { - const isFollowing = await this.followingsRepository.exists({ - where: { - followeeId: user.id, - followerId: me.id, - }, - }); - if (!isFollowing) { + if (profile.followersVisibility !== 'public' && !await this.roleService.isModerator(me)) { + if (profile.followersVisibility === 'private') { + if (me == null || (me.id !== user.id)) { throw new ApiError(meta.errors.forbidden); } + } else if (profile.followersVisibility === 'followers') { + if (me == null) { + throw new ApiError(meta.errors.forbidden); + } else if (me.id !== user.id) { + const isFollowing = await this.followingsRepository.exists({ + where: { + followeeId: user.id, + followerId: me.id, + }, + }); + if (!isFollowing) { + throw new ApiError(meta.errors.forbidden); + } + } } } diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 6b3389f0b2..feda5bb353 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -12,6 +12,7 @@ import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -90,6 +91,7 @@ export default class extends Endpoint { // eslint- private utilityService: UtilityService, private followingEntityService: FollowingEntityService, private queryService: QueryService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy(ps.userId != null @@ -102,23 +104,25 @@ export default class extends Endpoint { // eslint- const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); - if (profile.followingVisibility === 'private') { - if (me == null || (me.id !== user.id)) { - throw new ApiError(meta.errors.forbidden); - } - } else if (profile.followingVisibility === 'followers') { - if (me == null) { - throw new ApiError(meta.errors.forbidden); - } else if (me.id !== user.id) { - const isFollowing = await this.followingsRepository.exists({ - where: { - followeeId: user.id, - followerId: me.id, - }, - }); - if (!isFollowing) { + if (profile.followingVisibility !== 'public' && !await this.roleService.isModerator(me)) { + if (profile.followingVisibility === 'private') { + if (me == null || (me.id !== user.id)) { throw new ApiError(meta.errors.forbidden); } + } else if (profile.followingVisibility === 'followers') { + if (me == null) { + throw new ApiError(meta.errors.forbidden); + } else if (me.id !== user.id) { + const isFollowing = await this.followingsRepository.exists({ + where: { + followeeId: user.id, + followerId: me.id, + }, + }); + if (!isFollowing) { + throw new ApiError(meta.errors.forbidden); + } + } } } diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index cc76c12f1d..7fc11ba369 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -5,14 +5,13 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/_.js'; +import type { MiMeta, NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; import { QueryService } from '@/core/QueryService.js'; -import { MetaService } from '@/core/MetaService.js'; import { MiLocalUser } from '@/models/User.js'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; import { FanoutTimelineName } from '@/core/FanoutTimelineService.js'; @@ -67,6 +66,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.meta) + private serverSettings: MiMeta, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @@ -75,15 +77,12 @@ export default class extends Endpoint { // eslint- private cacheService: CacheService, private idService: IdService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService, - private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null); const isSelf = me && (me.id === ps.userId); - const serverSettings = await this.metaService.fetch(); - if (ps.withReplies && ps.withFiles) throw new ApiError(meta.errors.bothWithRepliesAndWithFiles); // early return if me is blocked by requesting user @@ -94,7 +93,7 @@ export default class extends Endpoint { // eslint- } } - if (!serverSettings.enableFanoutTimeline) { + if (!this.serverSettings.enableFanoutTimeline) { const timeline = await this.getFromDb({ untilId, sinceId, diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index aca883a052..7805ae3288 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -12,6 +12,7 @@ import { DI } from '@/di-symbols.js'; import { CacheService } from '@/core/CacheService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { RoleService } from '@/core/RoleService.js'; +import { isUserRelated } from '@/misc/is-user-related.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -74,6 +75,7 @@ export default class extends Endpoint { // eslint- private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { + const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set(); const iAmModerator = me ? await this.roleService.isModerator(me) : false; // Moderators can see reactions of all users if (!iAmModerator) { const user = await this.cacheService.findUserById(ps.userId); @@ -85,8 +87,15 @@ export default class extends Endpoint { // eslint- if ((me == null || me.id !== ps.userId) && !profile.publicReactions) { throw new ApiError(meta.errors.reactionsNotPublic); } + + // early return if me is blocked by requesting user + if (userIdsWhoBlockingMe.has(ps.userId)) { + return []; + } } + const userIdsWhoMeMuting = me ? await this.cacheService.userMutingsCache.fetch(me.id) : new Set(); + const query = this.queryService.makePaginationQuery(this.noteReactionsRepository.createQueryBuilder('reaction'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('reaction.userId = :userId', { userId: ps.userId }) @@ -94,9 +103,15 @@ export default class extends Endpoint { // eslint- this.queryService.generateVisibilityQuery(query, me); - const reactions = await query + const reactions = (await query .limit(ps.limit) - .getMany(); + .getMany()).filter(reaction => { + if (reaction.note?.userId === ps.userId) return true; // we can see reactions to note of requesting user + if (me && isUserRelated(reaction.note, userIdsWhoBlockingMe)) return false; + if (me && isUserRelated(reaction.note, userIdsWhoMeMuting)) return false; + + return true; + }); return await this.noteReactionEntityService.packMany(reactions, me, { withNote: true }); }); diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 7b3bdab327..8ff952dcb5 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -3,15 +3,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Brackets } from 'typeorm'; -import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, FollowingsRepository } from '@/models/_.js'; -import type { Config } from '@/config.js'; -import type { MiUser } from '@/models/User.js'; +import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { DI } from '@/di-symbols.js'; -import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; +import { UserSearchService } from '@/core/UserSearchService.js'; export const meta = { tags: ['users'], @@ -49,89 +43,16 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.config) - private config: Config, - - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - - @Inject(DI.followingsRepository) - private followingsRepository: FollowingsRepository, - - private userEntityService: UserEntityService, + private userSearchService: UserSearchService, ) { - super(meta, paramDef, async (ps, me) => { - const setUsernameAndHostQuery = (query = this.usersRepository.createQueryBuilder('user')) => { - if (ps.username) { - query.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }); - } - - if (ps.host) { - if (ps.host === this.config.hostname || ps.host === '.') { - query.andWhere('user.host IS NULL'); - } else { - query.andWhere('user.host LIKE :host', { - host: sqlLikeEscape(ps.host.toLowerCase()) + '%', - }); - } - } - - return query; - }; - - const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日 - - let users: MiUser[] = []; - - if (me) { - const followingQuery = this.followingsRepository.createQueryBuilder('following') - .select('following.followeeId') - .where('following.followerId = :followerId', { followerId: me.id }); - - const query = setUsernameAndHostQuery() - .andWhere(`user.id IN (${ followingQuery.getQuery() })`) - .andWhere('user.id != :meId', { meId: me.id }) - .andWhere('user.isSuspended = FALSE') - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })); - - query.setParameters(followingQuery.getParameters()); - - users = await query - .orderBy('user.usernameLower', 'ASC') - .limit(ps.limit) - .getMany(); - - if (users.length < ps.limit) { - const otherQuery = setUsernameAndHostQuery() - .andWhere(`user.id NOT IN (${ followingQuery.getQuery() })`) - .andWhere('user.isSuspended = FALSE') - .andWhere('user.updatedAt IS NOT NULL'); - - otherQuery.setParameters(followingQuery.getParameters()); - - const otherUsers = await otherQuery - .orderBy('user.updatedAt', 'DESC') - .limit(ps.limit - users.length) - .getMany(); - - users = users.concat(otherUsers); - } - } else { - const query = setUsernameAndHostQuery() - .andWhere('user.isSuspended = FALSE') - .andWhere('user.updatedAt IS NOT NULL'); - - users = await query - .orderBy('user.updatedAt', 'DESC') - .limit(ps.limit - users.length) - .getMany(); - } - - return await this.userEntityService.packMany(users, me, { schema: ps.detail ? 'UserDetailed' : 'UserLite' }); + super(meta, paramDef, (ps, me) => { + return this.userSearchService.search({ + username: ps.username, + host: ps.host, + }, { + limit: ps.limit, + detail: ps.detail, + }, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index df9d9f6312..0b0136066d 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -57,88 +57,66 @@ export default class extends Endpoint { // eslint- const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日 ps.query = ps.query.trim(); - const isUsername = ps.query.startsWith('@'); + const isUsername = ps.query.startsWith('@') && !ps.query.includes(' ') && ps.query.indexOf('@', 1) === -1; let users: MiUser[] = []; - if (isUsername) { - const usernameQuery = this.usersRepository.createQueryBuilder('user') - .where('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }) - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })) - .andWhere('user.isSuspended = FALSE'); + const nameQuery = this.usersRepository.createQueryBuilder('user') + .where(new Brackets(qb => { + qb.where('user.name ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); - if (ps.origin === 'local') { - usernameQuery.andWhere('user.host IS NULL'); - } else if (ps.origin === 'remote') { - usernameQuery.andWhere('user.host IS NOT NULL'); - } - - users = await usernameQuery - .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .limit(ps.limit) - .offset(ps.offset) - .getMany(); - } else { - const nameQuery = this.usersRepository.createQueryBuilder('user') - .where(new Brackets(qb => { - qb.where('user.name ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); - - // Also search username if it qualifies as username - if (this.userEntityService.validateLocalUsername(ps.query)) { - qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); - } - })) - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })) - .andWhere('user.isSuspended = FALSE'); - - if (ps.origin === 'local') { - nameQuery.andWhere('user.host IS NULL'); - } else if (ps.origin === 'remote') { - nameQuery.andWhere('user.host IS NOT NULL'); - } - - users = await nameQuery - .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .limit(ps.limit) - .offset(ps.offset) - .getMany(); - - if (users.length < ps.limit) { - const profQuery = this.userProfilesRepository.createQueryBuilder('prof') - .select('prof.userId') - .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); - - if (ps.origin === 'local') { - profQuery.andWhere('prof.userHost IS NULL'); - } else if (ps.origin === 'remote') { - profQuery.andWhere('prof.userHost IS NOT NULL'); + if (isUsername) { + qb.orWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }); + } else if (this.userEntityService.validateLocalUsername(ps.query)) { // Also search username if it qualifies as username + qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); } + })) + .andWhere(new Brackets(qb => { + qb + .where('user.updatedAt IS NULL') + .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); + })) + .andWhere('user.isSuspended = FALSE'); - const query = this.usersRepository.createQueryBuilder('user') - .where(`user.id IN (${ profQuery.getQuery() })`) - .andWhere(new Brackets(qb => { - qb - .where('user.updatedAt IS NULL') - .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); - })) - .andWhere('user.isSuspended = FALSE') - .setParameters(profQuery.getParameters()); + if (ps.origin === 'local') { + nameQuery.andWhere('user.host IS NULL'); + } else if (ps.origin === 'remote') { + nameQuery.andWhere('user.host IS NOT NULL'); + } - users = users.concat(await query - .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .limit(ps.limit) - .offset(ps.offset) - .getMany(), - ); + users = await nameQuery + .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') + .limit(ps.limit) + .offset(ps.offset) + .getMany(); + + if (users.length < ps.limit) { + const profQuery = this.userProfilesRepository.createQueryBuilder('prof') + .select('prof.userId') + .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); + + if (ps.origin === 'local') { + profQuery.andWhere('prof.userHost IS NULL'); + } else if (ps.origin === 'remote') { + profQuery.andWhere('prof.userHost IS NOT NULL'); } + + const query = this.usersRepository.createQueryBuilder('user') + .where(`user.id IN (${ profQuery.getQuery() })`) + .andWhere(new Brackets(qb => { + qb + .where('user.updatedAt IS NULL') + .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); + })) + .andWhere('user.isSuspended = FALSE') + .setParameters(profQuery.getParameters()); + + users = users.concat(await query + .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') + .limit(ps.limit) + .offset(ps.offset) + .getMany(), + ); } return await this.userEntityService.packMany(users, me, { schema: ps.detail ? 'UserDetailed' : 'UserLite' }); diff --git a/packages/backend/src/server/api/openapi/OpenApiServerService.ts b/packages/backend/src/server/api/openapi/OpenApiServerService.ts index 5210e4d2bc..f124aa9f39 100644 --- a/packages/backend/src/server/api/openapi/OpenApiServerService.ts +++ b/packages/backend/src/server/api/openapi/OpenApiServerService.ts @@ -25,7 +25,7 @@ export class OpenApiServerService { public createServer(fastify: FastifyInstance, _options: FastifyPluginOptions, done: (err?: Error) => void) { fastify.get('/api-doc', async (_request, reply) => { reply.header('Cache-Control', 'public, max-age=86400'); - return await reply.sendFile('/redoc.html', staticAssets); + return await reply.sendFile('/api-doc.html', staticAssets); }); fastify.get('/api.json', (_request, reply) => { reply.header('Cache-Control', 'public, max-age=600'); diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 2a14270a24..efa47a6986 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -15,7 +15,6 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) { info: { version: config.version, title: 'Misskey API', - 'x-logo': { url: '/static-assets/api-doc.png' }, }, externalDocs: { diff --git a/packages/backend/src/server/api/stream/Connection.ts b/packages/backend/src/server/api/stream/Connection.ts index 41c0feccc7..0fb5238c78 100644 --- a/packages/backend/src/server/api/stream/Connection.ts +++ b/packages/backend/src/server/api/stream/Connection.ts @@ -14,10 +14,14 @@ import { CacheService } from '@/core/CacheService.js'; import { MiFollowing, MiUserProfile } from '@/models/_.js'; import type { StreamEventEmitter, GlobalEvents } from '@/core/GlobalEventService.js'; import { ChannelFollowingService } from '@/core/ChannelFollowingService.js'; +import { isJsonObject } from '@/misc/json-value.js'; +import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import type { ChannelsService } from './ChannelsService.js'; import type { EventEmitter } from 'events'; import type Channel from './channel.js'; +const MAX_CHANNELS_PER_CONNECTION = 32; + /** * Main stream connection */ @@ -28,7 +32,7 @@ export default class Connection { private wsConnection: WebSocket.WebSocket; public subscriber: StreamEventEmitter; private channels: Channel[] = []; - private subscribingNotes: any = {}; + private subscribingNotes: Partial> = {}; private cachedNotes: Packed<'Note'>[] = []; public userProfile: MiUserProfile | null = null; public following: Record | undefined> = {}; @@ -101,7 +105,7 @@ export default class Connection { */ @bindThis private async onWsConnectionMessage(data: WebSocket.RawData) { - let obj: Record; + let obj: JsonObject; try { obj = JSON.parse(data.toString()); @@ -151,7 +155,8 @@ export default class Connection { } @bindThis - private readNote(body: any) { + private readNote(body: JsonValue | undefined) { + if (!isJsonObject(body)) return; const id = body.id; const note = this.cachedNotes.find(n => n.id === id); @@ -163,7 +168,7 @@ export default class Connection { } @bindThis - private onReadNotification(payload: any) { + private onReadNotification(payload: JsonValue | undefined) { this.notificationService.readAllNotification(this.user!.id); } @@ -171,16 +176,15 @@ export default class Connection { * 投稿購読要求時 */ @bindThis - private onSubscribeNote(payload: any) { - if (!payload.id) return; + private onSubscribeNote(payload: JsonValue | undefined) { + if (!isJsonObject(payload)) return; + if (!payload.id || typeof payload.id !== 'string') return; - if (this.subscribingNotes[payload.id] == null) { - this.subscribingNotes[payload.id] = 0; - } + const current = this.subscribingNotes[payload.id] ?? 0; + const updated = current + 1; + this.subscribingNotes[payload.id] = updated; - this.subscribingNotes[payload.id]++; - - if (this.subscribingNotes[payload.id] === 1) { + if (updated === 1) { this.subscriber.on(`noteStream:${payload.id}`, this.onNoteStreamMessage); } } @@ -189,11 +193,15 @@ export default class Connection { * 投稿購読解除要求時 */ @bindThis - private onUnsubscribeNote(payload: any) { - if (!payload.id) return; + private onUnsubscribeNote(payload: JsonValue | undefined) { + if (!isJsonObject(payload)) return; + if (!payload.id || typeof payload.id !== 'string') return; - this.subscribingNotes[payload.id]--; - if (this.subscribingNotes[payload.id] <= 0) { + const current = this.subscribingNotes[payload.id]; + if (current == null) return; + const updated = current - 1; + this.subscribingNotes[payload.id] = updated; + if (updated <= 0) { delete this.subscribingNotes[payload.id]; this.subscriber.off(`noteStream:${payload.id}`, this.onNoteStreamMessage); } @@ -212,17 +220,24 @@ export default class Connection { * チャンネル接続要求時 */ @bindThis - private onChannelConnectRequested(payload: any) { + private onChannelConnectRequested(payload: JsonValue | undefined) { + if (!isJsonObject(payload)) return; const { channel, id, params, pong } = payload; - this.connectChannel(id, params, channel, pong); + if (typeof id !== 'string') return; + if (typeof channel !== 'string') return; + if (typeof pong !== 'boolean' && typeof pong !== 'undefined' && pong !== null) return; + if (typeof params !== 'undefined' && !isJsonObject(params)) return; + this.connectChannel(id, params, channel, pong ?? undefined); } /** * チャンネル切断要求時 */ @bindThis - private onChannelDisconnectRequested(payload: any) { + private onChannelDisconnectRequested(payload: JsonValue | undefined) { + if (!isJsonObject(payload)) return; const { id } = payload; + if (typeof id !== 'string') return; this.disconnectChannel(id); } @@ -230,7 +245,7 @@ export default class Connection { * クライアントにメッセージ送信 */ @bindThis - public sendMessageToWs(type: string, payload: any) { + public sendMessageToWs(type: string, payload: JsonObject) { this.wsConnection.send(JSON.stringify({ type: type, body: payload, @@ -241,7 +256,11 @@ export default class Connection { * チャンネルに接続 */ @bindThis - public connectChannel(id: string, params: any, channel: string, pong = false) { + public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) { + if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) { + return; + } + const channelService = this.channelsService.getChannelService(channel); if (channelService.requireCredential && this.user == null) { @@ -288,7 +307,12 @@ export default class Connection { * @param data メッセージ */ @bindThis - private onChannelMessageRequested(data: any) { + private onChannelMessageRequested(data: JsonValue | undefined) { + if (!isJsonObject(data)) return; + if (typeof data.id !== 'string') return; + if (typeof data.type !== 'string') return; + if (typeof data.body === 'undefined') return; + const channel = this.channels.find(c => c.id === data.id); if (channel != null && channel.onMessage != null) { channel.onMessage(data.type, data.body); diff --git a/packages/backend/src/server/api/stream/channel.ts b/packages/backend/src/server/api/stream/channel.ts index a267d27fba..84cb552369 100644 --- a/packages/backend/src/server/api/stream/channel.ts +++ b/packages/backend/src/server/api/stream/channel.ts @@ -8,6 +8,7 @@ import { isInstanceMuted } from '@/misc/is-instance-muted.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; import type { Packed } from '@/misc/json-schema.js'; +import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import type Connection from './Connection.js'; /** @@ -81,10 +82,12 @@ export default abstract class Channel { this.connection = connection; } + public send(payload: { type: string, body: JsonValue }): void + public send(type: string, payload: JsonValue): void @bindThis - public send(typeOrPayload: any, payload?: any) { - const type = payload === undefined ? typeOrPayload.type : typeOrPayload; - const body = payload === undefined ? typeOrPayload.body : payload; + public send(typeOrPayload: { type: string, body: JsonValue } | string, payload?: JsonValue) { + const type = payload === undefined ? (typeOrPayload as { type: string, body: JsonValue }).type : (typeOrPayload as string); + const body = payload === undefined ? (typeOrPayload as { type: string, body: JsonValue }).body : payload; this.connection.sendMessageToWs('channel', { id: this.id, @@ -93,11 +96,11 @@ export default abstract class Channel { }); } - public abstract init(params: any): void; + public abstract init(params: JsonObject): void; public dispose?(): void; - public onMessage?(type: string, body: any): void; + public onMessage?(type: string, body: JsonValue): void; } export type MiChannelService = { diff --git a/packages/backend/src/server/api/stream/channels/admin.ts b/packages/backend/src/server/api/stream/channels/admin.ts index 92b6d2ac04..355d5dba21 100644 --- a/packages/backend/src/server/api/stream/channels/admin.ts +++ b/packages/backend/src/server/api/stream/channels/admin.ts @@ -5,6 +5,7 @@ import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class AdminChannel extends Channel { @@ -14,7 +15,7 @@ class AdminChannel extends Channel { public static kind = 'read:admin:stream'; @bindThis - public async init(params: any) { + public async init(params: JsonObject) { // Subscribe admin stream this.subscriber.on(`adminStream:${this.user!.id}`, data => { this.send(data); diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index 4a1d2dd109..53dc7f18b6 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -7,6 +7,7 @@ import { Injectable } from '@nestjs/common'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class AntennaChannel extends Channel { @@ -27,8 +28,9 @@ class AntennaChannel extends Channel { } @bindThis - public async init(params: any) { - this.antennaId = params.antennaId as string; + public async init(params: JsonObject) { + if (typeof params.antennaId !== 'string') return; + this.antennaId = params.antennaId; // Subscribe stream this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent); diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts index 140dd3dd9b..7108e0cd6e 100644 --- a/packages/backend/src/server/api/stream/channels/channel.ts +++ b/packages/backend/src/server/api/stream/channels/channel.ts @@ -8,6 +8,7 @@ import type { Packed } from '@/misc/json-schema.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class ChannelChannel extends Channel { @@ -27,8 +28,9 @@ class ChannelChannel extends Channel { } @bindThis - public async init(params: any) { - this.channelId = params.channelId as string; + public async init(params: JsonObject) { + if (typeof params.channelId !== 'string') return; + this.channelId = params.channelId; // Subscribe stream this.subscriber.on('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/drive.ts b/packages/backend/src/server/api/stream/channels/drive.ts index 0d9b486305..03768f3d23 100644 --- a/packages/backend/src/server/api/stream/channels/drive.ts +++ b/packages/backend/src/server/api/stream/channels/drive.ts @@ -5,6 +5,7 @@ import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class DriveChannel extends Channel { @@ -14,7 +15,7 @@ class DriveChannel extends Channel { public static kind = 'read:account'; @bindThis - public async init(params: any) { + public async init(params: JsonObject) { // Subscribe drive stream this.subscriber.on(`driveStream:${this.user!.id}`, data => { this.send(data); diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index 17116258d8..ed56fe0d40 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class GlobalTimelineChannel extends Channel { @@ -32,12 +33,12 @@ class GlobalTimelineChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.gtlAvailable) return; - this.withRenotes = params.withRenotes ?? true; - this.withFiles = params.withFiles ?? false; + this.withRenotes = !!(params.withRenotes ?? true); + this.withFiles = !!(params.withFiles ?? false); // Subscribe events this.subscriber.on('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts index 57bada5d9c..8105f15cb1 100644 --- a/packages/backend/src/server/api/stream/channels/hashtag.ts +++ b/packages/backend/src/server/api/stream/channels/hashtag.ts @@ -9,6 +9,7 @@ import type { Packed } from '@/misc/json-schema.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class HashtagChannel extends Channel { @@ -28,11 +29,11 @@ class HashtagChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { + if (!Array.isArray(params.q)) return; + if (!params.q.every(x => Array.isArray(x) && x.every(y => typeof y === 'string'))) return; this.q = params.q; - if (this.q == null) return; - // Subscribe stream this.subscriber.on('notesStream', this.onNote); } diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 878a3180cb..66644ed58c 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -8,6 +8,7 @@ import type { Packed } from '@/misc/json-schema.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class HomeTimelineChannel extends Channel { @@ -29,9 +30,9 @@ class HomeTimelineChannel extends Channel { } @bindThis - public async init(params: any) { - this.withRenotes = params.withRenotes ?? true; - this.withFiles = params.withFiles ?? false; + public async init(params: JsonObject) { + this.withRenotes = !!(params.withRenotes ?? true); + this.withFiles = !!(params.withFiles ?? false); this.subscriber.on('notesStream', this.onNote); } @@ -59,7 +60,7 @@ class HomeTimelineChannel extends Channel { const reply = note.reply; if (this.following[note.userId]?.withReplies) { // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く - if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return; } else { // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; @@ -72,7 +73,7 @@ class HomeTimelineChannel extends Channel { if (note.renote.reply) { const reply = note.renote.reply; // 自分のフォローしていないユーザーの visibility: followers な投稿への返信のリノートは弾く - if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return; } } diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index 575d23d53c..75bd13221f 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class HybridTimelineChannel extends Channel { @@ -34,13 +35,13 @@ class HybridTimelineChannel extends Channel { } @bindThis - public async init(params: any): Promise { + public async init(params: JsonObject): Promise { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.ltlAvailable) return; - this.withRenotes = params.withRenotes ?? true; - this.withReplies = params.withReplies ?? false; - this.withFiles = params.withFiles ?? false; + this.withRenotes = !!(params.withRenotes ?? true); + this.withReplies = !!(params.withReplies ?? false); + this.withFiles = !!(params.withFiles ?? false); // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -75,14 +76,22 @@ class HybridTimelineChannel extends Channel { const reply = note.reply; if ((this.following[note.userId]?.withReplies ?? false) || this.withReplies) { // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く - if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return; } else { // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; } } - if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; + // 純粋なリノート(引用リノートでないリノート)の場合 + if (isRenotePacked(note) && !isQuotePacked(note) && note.renote) { + if (!this.withRenotes) return; + if (note.renote.reply) { + const reply = note.renote.reply; + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信のリノートは弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId) && reply.userId !== this.user!.id) return; + } + } if (this.user && note.renoteId && !note.text) { if (note.renote && Object.keys(note.renote.reactions).length > 0) { diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 442d08ae51..491029f5de 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class LocalTimelineChannel extends Channel { @@ -33,13 +34,13 @@ class LocalTimelineChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.ltlAvailable) return; - this.withRenotes = params.withRenotes ?? true; - this.withReplies = params.withReplies ?? false; - this.withFiles = params.withFiles ?? false; + this.withRenotes = !!(params.withRenotes ?? true); + this.withReplies = !!(params.withReplies ?? false); + this.withFiles = !!(params.withFiles ?? false); // Subscribe events this.subscriber.on('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/main.ts b/packages/backend/src/server/api/stream/channels/main.ts index a12976d69d..863d7f4c4e 100644 --- a/packages/backend/src/server/api/stream/channels/main.ts +++ b/packages/backend/src/server/api/stream/channels/main.ts @@ -7,6 +7,7 @@ import { Injectable } from '@nestjs/common'; import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class MainChannel extends Channel { @@ -25,7 +26,7 @@ class MainChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { // Subscribe main stream channel this.subscriber.on(`mainStream:${this.user!.id}`, async data => { switch (data.type) { diff --git a/packages/backend/src/server/api/stream/channels/queue-stats.ts b/packages/backend/src/server/api/stream/channels/queue-stats.ts index 061aa76904..91b62255b4 100644 --- a/packages/backend/src/server/api/stream/channels/queue-stats.ts +++ b/packages/backend/src/server/api/stream/channels/queue-stats.ts @@ -6,6 +6,8 @@ import Xev from 'xev'; import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import { isJsonObject } from '@/misc/json-value.js'; +import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; const ev = new Xev(); @@ -22,19 +24,22 @@ class QueueStatsChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { ev.addListener('queueStats', this.onStats); } @bindThis - private onStats(stats: any) { + private onStats(stats: JsonObject) { this.send('stats', stats); } @bindThis - public onMessage(type: string, body: any) { + public onMessage(type: string, body: JsonValue) { switch (type) { case 'requestLog': + if (!isJsonObject(body)) return; + if (typeof body.id !== 'string') return; + if (typeof body.length !== 'number') return; ev.once(`queueStatsLog:${body.id}`, statsLog => { this.send('statsLog', statsLog); }); diff --git a/packages/backend/src/server/api/stream/channels/reversi-game.ts b/packages/backend/src/server/api/stream/channels/reversi-game.ts index f4a3a09367..7597a1cfa3 100644 --- a/packages/backend/src/server/api/stream/channels/reversi-game.ts +++ b/packages/backend/src/server/api/stream/channels/reversi-game.ts @@ -9,7 +9,10 @@ import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { ReversiService } from '@/core/ReversiService.js'; import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js'; +import { isJsonObject } from '@/misc/json-value.js'; +import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; +import { reversiUpdateKeys } from 'misskey-js'; class ReversiGameChannel extends Channel { public readonly chName = 'reversiGame'; @@ -28,25 +31,42 @@ class ReversiGameChannel extends Channel { } @bindThis - public async init(params: any) { - this.gameId = params.gameId as string; + public async init(params: JsonObject) { + if (typeof params.gameId !== 'string') return; + this.gameId = params.gameId; this.subscriber.on(`reversiGameStream:${this.gameId}`, this.send); } @bindThis - public onMessage(type: string, body: any) { + public onMessage(type: string, body: JsonValue) { switch (type) { - case 'ready': this.ready(body); break; - case 'updateSettings': this.updateSettings(body.key, body.value); break; - case 'cancel': this.cancelGame(); break; - case 'putStone': this.putStone(body.pos, body.id); break; + case 'ready': + if (typeof body !== 'boolean') return; + this.ready(body); + break; + case 'updateSettings': + if (!isJsonObject(body)) return; + if (!this.reversiService.isValidReversiUpdateKey(body.key)) return; + if (!this.reversiService.isValidReversiUpdateValue(body.key, body.value)) return; + + this.updateSettings(body.key, body.value); + break; + case 'cancel': + this.cancelGame(); + break; + case 'putStone': + if (!isJsonObject(body)) return; + if (typeof body.pos !== 'number') return; + if (typeof body.id !== 'string') return; + this.putStone(body.pos, body.id); + break; case 'claimTimeIsUp': this.claimTimeIsUp(); break; } } @bindThis - private async updateSettings(key: string, value: any) { + private async updateSettings(key: K, value: MiReversiGame[K]) { if (this.user == null) return; this.reversiService.updateSettings(this.gameId!, this.user, key, value); diff --git a/packages/backend/src/server/api/stream/channels/reversi.ts b/packages/backend/src/server/api/stream/channels/reversi.ts index 3998a0fd36..6e88939724 100644 --- a/packages/backend/src/server/api/stream/channels/reversi.ts +++ b/packages/backend/src/server/api/stream/channels/reversi.ts @@ -5,6 +5,7 @@ import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class ReversiChannel extends Channel { @@ -21,7 +22,7 @@ class ReversiChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { this.subscriber.on(`reversiStream:${this.user!.id}`, this.send); } diff --git a/packages/backend/src/server/api/stream/channels/role-timeline.ts b/packages/backend/src/server/api/stream/channels/role-timeline.ts index 6a4ad22460..fcfa26c38b 100644 --- a/packages/backend/src/server/api/stream/channels/role-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/role-timeline.ts @@ -8,6 +8,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class RoleTimelineChannel extends Channel { @@ -28,8 +29,9 @@ class RoleTimelineChannel extends Channel { } @bindThis - public async init(params: any) { - this.roleId = params.roleId as string; + public async init(params: JsonObject) { + if (typeof params.roleId !== 'string') return; + this.roleId = params.roleId; this.subscriber.on(`roleTimelineStream:${this.roleId}`, this.onEvent); } diff --git a/packages/backend/src/server/api/stream/channels/server-stats.ts b/packages/backend/src/server/api/stream/channels/server-stats.ts index eb4d8c9992..ec5352d12d 100644 --- a/packages/backend/src/server/api/stream/channels/server-stats.ts +++ b/packages/backend/src/server/api/stream/channels/server-stats.ts @@ -6,6 +6,8 @@ import Xev from 'xev'; import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import { isJsonObject } from '@/misc/json-value.js'; +import type { JsonObject, JsonValue } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; const ev = new Xev(); @@ -22,19 +24,20 @@ class ServerStatsChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { ev.addListener('serverStats', this.onStats); } @bindThis - private onStats(stats: any) { + private onStats(stats: JsonObject) { this.send('stats', stats); } @bindThis - public onMessage(type: string, body: any) { + public onMessage(type: string, body: JsonValue) { switch (type) { case 'requestLog': + if (!isJsonObject(body)) return; ev.once(`serverStatsLog:${body.id}`, statsLog => { this.send('statsLog', statsLog); }); diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index 14b30a157c..4f38351e94 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { type MiChannelService } from '../channel.js'; class UserListChannel extends Channel { @@ -36,10 +37,11 @@ class UserListChannel extends Channel { } @bindThis - public async init(params: any) { - this.listId = params.listId as string; - this.withFiles = params.withFiles ?? false; - this.withRenotes = params.withRenotes ?? true; + public async init(params: JsonObject) { + if (typeof params.listId !== 'string') return; + this.listId = params.listId; + this.withFiles = !!(params.withFiles ?? false); + this.withRenotes = !!(params.withRenotes ?? true); // Check existence and owner const listExist = await this.userListsRepository.exists({ diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index f55790b636..dd7bb7823e 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url'; import { Inject, Injectable } from '@nestjs/common'; import { createBullBoard } from '@bull-board/api'; import { BullMQAdapter } from '@bull-board/api/bullMQAdapter.js'; -import { FastifyAdapter } from '@bull-board/fastify'; +import { FastifyAdapter as BullBoardFastifyAdapter } from '@bull-board/fastify'; import ms from 'ms'; import sharp from 'sharp'; import pug from 'pug'; @@ -24,7 +24,6 @@ import type { Config } from '@/config.js'; import { getNoteSummary } from '@/misc/get-note-summary.js'; import { DI } from '@/di-symbols.js'; import * as Acct from '@/misc/acct.js'; -import { MetaService } from '@/core/MetaService.js'; import type { DbQueue, DeliverQueue, @@ -61,7 +60,8 @@ const staticAssets = `${_dirname}/../../../assets/`; const clientAssets = `${_dirname}/../../../../frontend/assets/`; const assets = `${_dirname}/../../../../../built/_frontend_dist_/`; const swAssets = `${_dirname}/../../../../../built/_sw_dist_/`; -const viteOut = `${_dirname}/../../../../../built/_vite_/`; +const frontendViteOut = `${_dirname}/../../../../../built/_frontend_vite_/`; +const frontendEmbedViteOut = `${_dirname}/../../../../../built/_frontend_embed_vite_/`; const tarball = `${_dirname}/../../../../../built/tarball/`; @Injectable() @@ -72,6 +72,9 @@ export class ClientServerService { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -108,7 +111,6 @@ export class ClientServerService { private clipEntityService: ClipEntityService, private channelEntityService: ChannelEntityService, private reversiGameEntityService: ReversiGameEntityService, - private metaService: MetaService, private urlPreviewService: UrlPreviewService, private feedService: FeedService, private roleService: RoleService, @@ -128,32 +130,30 @@ export class ClientServerService { @bindThis private async manifestHandler(reply: FastifyReply) { - const instance = await this.metaService.fetch(true); - let manifest = { // 空文字列の場合右辺を使いたいため // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - 'short_name': instance.shortName || instance.name || this.config.host, + 'short_name': this.meta.shortName || this.meta.name || this.config.host, // 空文字列の場合右辺を使いたいため // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - 'name': instance.name || this.config.host, + 'name': this.meta.name || this.config.host, 'start_url': '/', 'display': 'standalone', 'background_color': '#313a42', // 空文字列の場合右辺を使いたいため // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - 'theme_color': instance.themeColor || '#86b300', + 'theme_color': this.meta.themeColor || '#86b300', 'icons': [{ // 空文字列の場合右辺を使いたいため // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - 'src': instance.app192IconUrl || '/static-assets/icons/192.png', + 'src': this.meta.app192IconUrl || '/static-assets/icons/192.png', 'sizes': '192x192', 'type': 'image/png', 'purpose': 'maskable', }, { // 空文字列の場合右辺を使いたいため // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - 'src': instance.app512IconUrl || '/static-assets/icons/512.png', + 'src': this.meta.app512IconUrl || '/static-assets/icons/512.png', 'sizes': '512x512', 'type': 'image/png', 'purpose': 'maskable', @@ -177,7 +177,7 @@ export class ClientServerService { manifest = { ...manifest, - ...JSON.parse(instance.manifestJsonOverride === '' ? '{}' : instance.manifestJsonOverride), + ...JSON.parse(this.meta.manifestJsonOverride === '' ? '{}' : this.meta.manifestJsonOverride), }; reply.header('Cache-Control', 'max-age=300'); @@ -239,7 +239,7 @@ export class ClientServerService { } }); - const serverAdapter = new FastifyAdapter(); + const bullBoardServerAdapter = new BullBoardFastifyAdapter(); createBullBoard({ queues: [ @@ -252,11 +252,11 @@ export class ClientServerService { this.userWebhookDeliverQueue, this.systemWebhookDeliverQueue, ].map(q => new BullMQAdapter(q)), - serverAdapter, + serverAdapter: bullBoardServerAdapter, }); - serverAdapter.setBasePath(bullBoardPath); - (fastify.register as any)(serverAdapter.registerPlugin(), { prefix: bullBoardPath }); + bullBoardServerAdapter.setBasePath(bullBoardPath); + (fastify.register as any)(bullBoardServerAdapter.registerPlugin(), { prefix: bullBoardPath }); //#endregion fastify.register(fastifyView, { @@ -277,15 +277,22 @@ export class ClientServerService { }); //#region vite assets - if (this.config.clientManifestExists) { + if (this.config.frontendEmbedManifestExists) { fastify.register((fastify, options, done) => { fastify.register(fastifyStatic, { - root: viteOut, + root: frontendViteOut, prefix: '/vite/', maxAge: ms('30 days'), immutable: true, decorateReply: false, }); + fastify.register(fastifyStatic, { + root: frontendEmbedViteOut, + prefix: '/embed_vite/', + maxAge: ms('30 days'), + immutable: true, + decorateReply: false, + }); fastify.addHook('onRequest', handleRequestRedirectToOmitSearch); done(); }); @@ -296,6 +303,13 @@ export class ClientServerService { prefix: '/vite', rewritePrefix: '/vite', }); + + const embedPort = (process.env.EMBED_VITE_PORT ?? '5174'); + fastify.register(fastifyProxy, { + upstream: 'http://localhost:' + embedPort, + prefix: '/embed_vite', + rewritePrefix: '/embed_vite', + }); } //#endregion @@ -425,15 +439,20 @@ export class ClientServerService { // Manifest fastify.get('/manifest.json', async (request, reply) => await this.manifestHandler(reply)); + // Embed Javascript + fastify.get('/embed.js', async (request, reply) => { + return await reply.sendFile('/embed.js', staticAssets, { + maxAge: ms('1 day'), + }); + }); + fastify.get('/robots.txt', async (request, reply) => { return await reply.sendFile('/robots.txt', staticAssets); }); // OpenSearch XML fastify.get('/opensearch.xml', async (request, reply) => { - const meta = await this.metaService.fetch(); - - const name = meta.name ?? 'Misskey'; + const name = this.meta.name ?? 'Misskey'; let content = ''; content += ''; content += `${name}`; @@ -450,14 +469,13 @@ export class ClientServerService { //#endregion const renderBase = async (reply: FastifyReply, data: { [key: string]: any } = {}) => { - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=30'); return await reply.view('base', { - img: meta.bannerUrl, + img: this.meta.bannerUrl, url: this.config.url, - title: meta.name ?? 'Misskey', - desc: meta.description, - ...await this.generateCommonPugData(meta), + title: this.meta.name ?? 'Misskey', + desc: this.meta.description, + ...await this.generateCommonPugData(this.meta), ...data, }); }; @@ -535,7 +553,6 @@ export class ClientServerService { if (user != null) { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); - const meta = await this.metaService.fetch(); const me = profile.fields ? profile.fields .filter(filed => filed.value != null && filed.value.match(/^https?:/)) @@ -551,7 +568,7 @@ export class ClientServerService { user, profile, me, avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), sub: request.params.sub, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { // リモートユーザーなので @@ -589,7 +606,6 @@ export class ClientServerService { if (note) { const _note = await this.noteEntityService.pack(note); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId }); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=15'); if (profile.preventAiLearning) { reply.header('X-Robots-Tag', 'noimageai'); @@ -601,7 +617,7 @@ export class ClientServerService { avatarUrl: _note.user.avatarUrl, // TODO: Let locale changeable by instance setting summary: getNoteSummary(_note), - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -626,7 +642,6 @@ export class ClientServerService { if (page) { const _page = await this.pageEntityService.pack(page); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: page.userId }); - const meta = await this.metaService.fetch(); if (['public'].includes(page.visibility)) { reply.header('Cache-Control', 'public, max-age=15'); } else { @@ -640,7 +655,7 @@ export class ClientServerService { page: _page, profile, avatarUrl: _page.user.avatarUrl, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -656,7 +671,6 @@ export class ClientServerService { if (flash) { const _flash = await this.flashEntityService.pack(flash); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: flash.userId }); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=15'); if (profile.preventAiLearning) { reply.header('X-Robots-Tag', 'noimageai'); @@ -666,7 +680,7 @@ export class ClientServerService { flash: _flash, profile, avatarUrl: _flash.user.avatarUrl, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -682,7 +696,6 @@ export class ClientServerService { if (clip && clip.isPublic) { const _clip = await this.clipEntityService.pack(clip); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: clip.userId }); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=15'); if (profile.preventAiLearning) { reply.header('X-Robots-Tag', 'noimageai'); @@ -692,7 +705,7 @@ export class ClientServerService { clip: _clip, profile, avatarUrl: _clip.user.avatarUrl, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -706,7 +719,6 @@ export class ClientServerService { if (post) { const _post = await this.galleryPostEntityService.pack(post); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: post.userId }); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=15'); if (profile.preventAiLearning) { reply.header('X-Robots-Tag', 'noimageai'); @@ -716,7 +728,7 @@ export class ClientServerService { post: _post, profile, avatarUrl: _post.user.avatarUrl, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -731,11 +743,10 @@ export class ClientServerService { if (channel) { const _channel = await this.channelEntityService.pack(channel); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=15'); return await reply.view('channel', { channel: _channel, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -750,11 +761,10 @@ export class ClientServerService { if (game) { const _game = await this.reversiGameEntityService.packDetail(game); - const meta = await this.metaService.fetch(); reply.header('Cache-Control', 'public, max-age=3600'); return await reply.view('reversi-game', { game: _game, - ...await this.generateCommonPugData(meta), + ...await this.generateCommonPugData(this.meta), }); } else { return await renderBase(reply); @@ -762,7 +772,7 @@ export class ClientServerService { }); //#endregion - //region noindex pages + //#region noindex pages // Tags fastify.get<{ Params: { clip: string; } }>('/tags/:tag', async (request, reply) => { return await renderBase(reply, { noindex: true }); @@ -772,21 +782,97 @@ export class ClientServerService { fastify.get<{ Params: { clip: string; } }>('/user-tags/:tag', async (request, reply) => { return await renderBase(reply, { noindex: true }); }); - //endregion + //#endregion + + //#region embed pages + fastify.get<{ Params: { user: string; } }>('/embed/user-timeline/:user', async (request, reply) => { + reply.removeHeader('X-Frame-Options'); + + const user = await this.usersRepository.findOneBy({ + id: request.params.user, + }); + + if (user == null) return; + if (user.host != null) return; + + const _user = await this.userEntityService.pack(user); + + reply.header('Cache-Control', 'public, max-age=3600'); + return await reply.view('base-embed', { + title: this.meta.name ?? 'Misskey', + ...await this.generateCommonPugData(this.meta), + embedCtx: htmlSafeJsonStringify({ + user: _user, + }), + }); + }); + + fastify.get<{ Params: { note: string; } }>('/embed/notes/:note', async (request, reply) => { + reply.removeHeader('X-Frame-Options'); + + const note = await this.notesRepository.findOneBy({ + id: request.params.note, + }); + + if (note == null) return; + if (note.visibility !== 'public') return; + if (note.userHost != null) return; + + const _note = await this.noteEntityService.pack(note, null, { detail: true }); + + reply.header('Cache-Control', 'public, max-age=3600'); + return await reply.view('base-embed', { + title: this.meta.name ?? 'Misskey', + ...await this.generateCommonPugData(this.meta), + embedCtx: htmlSafeJsonStringify({ + note: _note, + }), + }); + }); + + fastify.get<{ Params: { clip: string; } }>('/embed/clips/:clip', async (request, reply) => { + reply.removeHeader('X-Frame-Options'); + + const clip = await this.clipsRepository.findOneBy({ + id: request.params.clip, + }); + + if (clip == null) return; + + const _clip = await this.clipEntityService.pack(clip); + + reply.header('Cache-Control', 'public, max-age=3600'); + return await reply.view('base-embed', { + title: this.meta.name ?? 'Misskey', + ...await this.generateCommonPugData(this.meta), + embedCtx: htmlSafeJsonStringify({ + clip: _clip, + }), + }); + }); + + fastify.get('/embed/*', async (request, reply) => { + reply.removeHeader('X-Frame-Options'); + + reply.header('Cache-Control', 'public, max-age=3600'); + return await reply.view('base-embed', { + title: this.meta.name ?? 'Misskey', + ...await this.generateCommonPugData(this.meta), + }); + }); fastify.get('/_info_card_', async (request, reply) => { - const meta = await this.metaService.fetch(true); - reply.removeHeader('X-Frame-Options'); return await reply.view('info-card', { version: this.config.version, host: this.config.host, - meta: meta, + meta: this.meta, originalUsersCount: await this.usersRepository.countBy({ host: IsNull() }), originalNotesCount: await this.notesRepository.countBy({ userHost: IsNull() }), }); }); + //#endregion fastify.get('/bios', async (request, reply) => { return await reply.view('bios', { diff --git a/packages/backend/src/server/web/UrlPreviewService.ts b/packages/backend/src/server/web/UrlPreviewService.ts index 8f8f08a305..5d493c2c46 100644 --- a/packages/backend/src/server/web/UrlPreviewService.ts +++ b/packages/backend/src/server/web/UrlPreviewService.ts @@ -8,7 +8,6 @@ import { summaly } from '@misskey-dev/summaly'; import { SummalyResult } from '@misskey-dev/summaly/built/summary.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import { MetaService } from '@/core/MetaService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import type Logger from '@/logger.js'; import { query } from '@/misc/prelude/url.js'; @@ -26,7 +25,9 @@ export class UrlPreviewService { @Inject(DI.config) private config: Config, - private metaService: MetaService, + @Inject(DI.meta) + private meta: MiMeta, + private httpRequestService: HttpRequestService, private loggerService: LoggerService, ) { @@ -62,9 +63,7 @@ export class UrlPreviewService { return; } - const meta = await this.metaService.fetch(); - - if (!meta.urlPreviewEnabled) { + if (!this.meta.urlPreviewEnabled) { reply.code(403); return { error: new ApiError({ @@ -75,14 +74,14 @@ export class UrlPreviewService { }; } - this.logger.info(meta.urlPreviewSummaryProxyUrl + this.logger.info(this.meta.urlPreviewSummaryProxyUrl ? `(Proxy) Getting preview of ${url}@${lang} ...` : `Getting preview of ${url}@${lang} ...`); try { - const summary = meta.urlPreviewSummaryProxyUrl - ? await this.fetchSummaryFromProxy(url, meta, lang) - : await this.fetchSummary(url, meta, lang); + const summary = this.meta.urlPreviewSummaryProxyUrl + ? await this.fetchSummaryFromProxy(url, this.meta, lang) + : await this.fetchSummary(url, this.meta, lang); this.logger.succ(`Got preview of ${url}: ${summary.title}`); diff --git a/packages/backend/src/server/web/boot.embed.js b/packages/backend/src/server/web/boot.embed.js new file mode 100644 index 0000000000..48d1cd262b --- /dev/null +++ b/packages/backend/src/server/web/boot.embed.js @@ -0,0 +1,219 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +'use strict'; + +// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので +(async () => { + window.onerror = (e) => { + console.error(e); + renderError('SOMETHING_HAPPENED'); + }; + window.onunhandledrejection = (e) => { + console.error(e); + renderError('SOMETHING_HAPPENED_IN_PROMISE'); + }; + + let forceError = localStorage.getItem('forceError'); + if (forceError != null) { + renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.'); + return; + } + + // パラメータに応じてsplashのスタイルを変更 + const params = new URLSearchParams(location.search); + if (params.has('rounded') && params.get('rounded') === 'false') { + document.documentElement.classList.add('norounded'); + } + if (params.has('border') && params.get('border') === 'false') { + document.documentElement.classList.add('noborder'); + } + + //#region Detect language & fetch translations + if (!localStorage.hasOwnProperty('locale')) { + const supportedLangs = LANGS; + let lang = localStorage.getItem('lang'); + if (lang == null || !supportedLangs.includes(lang)) { + if (supportedLangs.includes(navigator.language)) { + lang = navigator.language; + } else { + lang = supportedLangs.find(x => x.split('-')[0] === navigator.language); + + // Fallback + if (lang == null) lang = 'en-US'; + } + } + + const metaRes = await window.fetch('/api/meta', { + method: 'POST', + body: JSON.stringify({}), + credentials: 'omit', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + }); + if (metaRes.status !== 200) { + renderError('META_FETCH'); + return; + } + const meta = await metaRes.json(); + const v = meta.version; + if (v == null) { + renderError('META_FETCH_V'); + return; + } + + // for https://github.com/misskey-dev/misskey/issues/10202 + if (lang == null || lang.toString == null || lang.toString() === 'null') { + console.error('invalid lang value detected!!!', typeof lang, lang); + lang = 'en-US'; + } + + const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`); + if (localRes.status === 200) { + localStorage.setItem('lang', lang); + localStorage.setItem('locale', await localRes.text()); + localStorage.setItem('localeVersion', v); + } else { + renderError('LOCALE_FETCH'); + return; + } + } + //#endregion + + //#region Script + async function importAppScript() { + await import(`/embed_vite/${CLIENT_ENTRY}`) + .catch(async e => { + console.error(e); + renderError('APP_IMPORT'); + }); + } + + // タイミングによっては、この時点でDOMの構築が済んでいる場合とそうでない場合とがある + if (document.readyState !== 'loading') { + importAppScript(); + } else { + window.addEventListener('DOMContentLoaded', () => { + importAppScript(); + }); + } + //#endregion + + async function addStyle(styleText) { + let css = document.createElement('style'); + css.appendChild(document.createTextNode(styleText)); + document.head.appendChild(css); + } + + async function renderError(code) { + // Cannot set property 'innerHTML' of null を回避 + if (document.readyState === 'loading') { + await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve)); + } + document.body.innerHTML = ` +

読み込みに失敗しました
+
Failed to initialize Misskey
+
Error Code: ${code}
+ `; + addStyle(` + #misskey_app, + #splash { + display: none !important; + } + + html, + body { + margin: 0; + } + + body { + position: relative; + color: #dee7e4; + font-family: Hiragino Maru Gothic Pro, BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; + line-height: 1.35; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + margin: 0; + padding: 24px; + box-sizing: border-box; + overflow: hidden; + + border-radius: var(--radius, 12px); + border: 1px solid rgba(231, 255, 251, 0.14); + } + + body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #192320; + border-radius: var(--radius, 12px); + z-index: -1; + } + + html.embed.norounded body, + html.embed.norounded body::before { + border-radius: 0; + } + + html.embed.noborder body { + border: none; + } + + .icon { + max-width: 60px; + width: 100%; + height: auto; + margin-bottom: 20px; + color: #dec340; + } + + .message { + text-align: center; + font-size: 20px; + font-weight: 700; + margin-bottom: 20px; + } + + .submessage { + text-align: center; + font-size: 90%; + margin-bottom: 7.5px; + } + + .submessage:last-of-type { + margin-bottom: 20px; + } + + button { + padding: 7px 14px; + min-width: 100px; + font-weight: 700; + font-family: Hiragino Maru Gothic Pro, BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; + line-height: 1.35; + border-radius: 99rem; + background-color: #b4e900; + color: #192320; + border: none; + cursor: pointer; + -webkit-tap-highlight-color: transparent; + } + + button:hover { + background-color: #c6ff03; + }`); + } +})(); diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 396536948e..a04640d993 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -3,17 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -/** - * BOOT LOADER - * サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。 - * - 翻訳ファイルをフェッチする。 - * - バージョンに基づいて適切なメインスクリプトを読み込む。 - * - キャッシュされたコンパイル済みテーマを適用する。 - * - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。 - * テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。 - * 注: webpackは介さないため、このファイルではrequireやimportは使えません。 - */ - 'use strict'; // ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので @@ -29,7 +18,8 @@ let forceError = localStorage.getItem('forceError'); if (forceError != null) { - renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.') + renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.'); + return; } //#region Detect language & fetch translations @@ -108,7 +98,7 @@ const theme = localStorage.getItem('theme'); if (theme) { for (const [k, v] of Object.entries(JSON.parse(theme))) { - document.documentElement.style.setProperty(`--${k}`, v.toString()); + document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString()); // HTMLの theme-color 適用 if (k === 'htmlThemeColor') { @@ -155,12 +145,17 @@ document.head.appendChild(css); } - function renderError(code, details) { + async function renderError(code, details) { + // Cannot set property 'innerHTML' of null を回避 + if (document.readyState === 'loading') { + await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve)); + } + let errorsElement = document.getElementById('errors'); if (!errorsElement) { document.body.innerHTML = ` - + @@ -170,10 +165,10 @@ Reload / リロード

The following actions may solve the problem. / 以下を行うと解決する可能性があります。

-

Clear the browser cache / ブラウザのキャッシュをクリアする

Update your os and browser / ブラウザおよびOSを最新バージョンに更新する

Disable an adblocker / アドブロッカーを無効にする

-

(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する

+

Clear the browser cache / ブラウザのキャッシュをクリアする

+

(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する

Other options / その他のオプション @@ -206,7 +201,7 @@ ERROR CODE: ${code} - ${JSON.stringify(details)}`; + ${details.toString()} ${JSON.stringify(details)}`; errorsElement.appendChild(detailsElement); addStyle(` * { @@ -314,6 +309,6 @@ #errorInfo { width: 50%; } - `) + }`); } })(); diff --git a/packages/backend/src/server/web/style.css b/packages/backend/src/server/web/style.css index e4723c24fd..5d81f2bed0 100644 --- a/packages/backend/src/server/web/style.css +++ b/packages/backend/src/server/web/style.css @@ -5,8 +5,8 @@ */ html { - background-color: var(--bg); - color: var(--fg); + background-color: var(--MI_THEME-bg); + color: var(--MI_THEME-fg); } #splash { @@ -17,7 +17,7 @@ html { width: 100vw; height: 100vh; cursor: wait; - background-color: var(--bg); + background-color: var(--MI_THEME-bg); opacity: 1; transition: opacity 0.5s ease; } @@ -45,8 +45,9 @@ html { width: 28px; height: 28px; transform: translateY(70px); - color: var(--accent); + color: var(--MI_THEME-accent); } + #splashSpinner > .spinner { position: absolute; top: 0; diff --git a/packages/backend/src/server/web/style.embed.css b/packages/backend/src/server/web/style.embed.css new file mode 100644 index 0000000000..5e8786cc4e --- /dev/null +++ b/packages/backend/src/server/web/style.embed.css @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +html { + background-color: var(--MI_THEME-bg); + color: var(--MI_THEME-fg); +} + +html.embed { + box-sizing: border-box; + background-color: transparent; + color-scheme: light dark; + max-width: 500px; +} + +#splash { + position: fixed; + z-index: 10000; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + cursor: wait; + background-color: var(--MI_THEME-bg); + opacity: 1; + transition: opacity 0.5s ease; +} + +html.embed #splash { + box-sizing: border-box; + min-height: 300px; + border-radius: var(--radius, 12px); + border: 1px solid var(--MI_THEME-divider, #e8e8e8); +} + +html.embed.norounded #splash { + border-radius: 0; +} + +html.embed.noborder #splash { + border: none; +} + +#splashIcon { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + width: 64px; + height: 64px; + pointer-events: none; +} + +#splashSpinner { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + display: inline-block; + width: 28px; + height: 28px; + transform: translateY(70px); + color: var(--MI_THEME-accent); +} + +#splashSpinner > .spinner { + position: absolute; + top: 0; + left: 0; + width: 28px; + height: 28px; + fill-rule: evenodd; + clip-rule: evenodd; + stroke-linecap: round; + stroke-linejoin: round; + stroke-miterlimit: 1.5; +} +#splashSpinner > .spinner.bg { + opacity: 0.275; +} +#splashSpinner > .spinner.fg { + animation: splashSpinner 0.5s linear infinite; +} + +@keyframes splashSpinner { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/packages/backend/src/server/web/views/base-embed.pug b/packages/backend/src/server/web/views/base-embed.pug new file mode 100644 index 0000000000..baa0909676 --- /dev/null +++ b/packages/backend/src/server/web/views/base-embed.pug @@ -0,0 +1,72 @@ +block vars + +block loadClientEntry + - const entry = config.frontendEmbedEntry; + +doctype html + +html(class='embed') + + head + meta(charset='utf-8') + meta(name='application-name' content='Misskey') + meta(name='referrer' content='origin') + meta(name='theme-color' content= themeColor || '#86b300') + meta(name='theme-color-orig' content= themeColor || '#86b300') + meta(property='og:site_name' content= instanceName || 'Misskey') + meta(property='instance_url' content= instanceUrl) + meta(name='viewport' content='width=device-width, initial-scale=1') + meta(name='format-detection' content='telephone=no,date=no,address=no,email=no,url=no') + link(rel='icon' href= icon || '/favicon.ico') + link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png') + link(rel='modulepreload' href=`/embed_vite/${entry.file}`) + + if !config.frontendEmbedManifestExists + script(type="module" src="/embed_vite/@vite/client") + + if Array.isArray(entry.css) + each href in entry.css + link(rel='stylesheet' href=`/embed_vite/${href}`) + + title + block title + = title || 'Misskey' + + block meta + meta(name='robots' content='noindex') + + style + include ../style.embed.css + + script. + var VERSION = "#{version}"; + var CLIENT_ENTRY = "#{entry.file}"; + + script(type='application/json' id='misskey_meta' data-generated-at=now) + != metaJson + + script(type='application/json' id='misskey_embedCtx' data-generated-at=now) + != embedCtx + + script + include ../boot.embed.js + + body + noscript: p + | JavaScriptを有効にしてください + br + | Please turn on your JavaScript + div#splash + img#splashIcon(src= icon || '/static-assets/splash.png') + div#splashSpinner + + + + + + + + + + + block content diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index ec1325e4e9..88714b2556 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -1,7 +1,7 @@ block vars block loadClientEntry - - const clientEntry = config.clientEntry; + - const entry = config.frontendEntry; doctype html @@ -28,6 +28,7 @@ html meta(property='og:site_name' content= instanceName || 'Misskey') meta(property='instance_url' content= instanceUrl) meta(name='viewport' content='width=device-width, initial-scale=1') + meta(name='format-detection' content='telephone=no,date=no,address=no,email=no,url=no') link(rel='icon' href= icon || '/favicon.ico') link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png') link(rel='manifest' href='/manifest.json') @@ -35,15 +36,13 @@ html link(rel='prefetch' href=serverErrorImageUrl) link(rel='prefetch' href=infoImageUrl) link(rel='prefetch' href=notFoundImageUrl) - //- https://github.com/misskey-dev/misskey/issues/9842 - link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v3.3.0') - link(rel='modulepreload' href=`/vite/${clientEntry.file}`) + link(rel='modulepreload' href=`/vite/${entry.file}`) - if !config.clientManifestExists + if !config.frontendManifestExists script(type="module" src="/vite/@vite/client") - if Array.isArray(clientEntry.css) - each href in clientEntry.css + if Array.isArray(entry.css) + each href in entry.css link(rel='stylesheet' href=`/vite/${href}`) title @@ -69,7 +68,7 @@ html script. var VERSION = "#{version}"; - var CLIENT_ENTRY = "#{clientEntry.file}"; + var CLIENT_ENTRY = "#{entry.file}"; script(type='application/json' id='misskey_meta' data-generated-at=now) != metaJson diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index ecbbee4eff..df3cfee171 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -16,6 +16,8 @@ * followRequestAccepted - 自分の送ったフォローリクエストが承認された * roleAssigned - ロールが付与された * achievementEarned - 実績を獲得 + * exportCompleted - エクスポートが完了 + * login - ログイン * app - アプリ通知 * test - テスト通知(サーバー側) */ @@ -32,6 +34,8 @@ export const notificationTypes = [ 'followRequestAccepted', 'roleAssigned', 'achievementEarned', + 'exportCompleted', + 'login', 'app', 'test', ] as const; @@ -51,6 +55,20 @@ export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const; export const followingVisibilities = ['public', 'followers', 'private'] as const; export const followersVisibilities = ['public', 'followers', 'private'] as const; +/** + * ユーザーがエクスポートできるものの種類 + * + * (主にエクスポート完了通知で使用するものであり、既存のDBの名称等と必ずしも一致しない) + */ +export const userExportableEntities = ['antenna', 'blocking', 'clip', 'customEmoji', 'favorite', 'following', 'muting', 'note', 'userList'] as const; + +/** + * ユーザーがインポートできるものの種類 + * + * (主にインポート完了通知で使用するものであり、既存のDBの名称等と必ずしも一致しない) + */ +export const userImportableEntities = ['antenna', 'blocking', 'customEmoji', 'following', 'muting', 'userList'] as const; + export const moderationLogTypes = [ 'updateServerSettings', 'suspend', @@ -81,6 +99,8 @@ export const moderationLogTypes = [ 'markSensitiveDriveFile', 'unmarkSensitiveDriveFile', 'resolveAbuseReport', + 'forwardAbuseReport', + 'updateAbuseReportNote', 'createInvitation', 'createAd', 'updateAd', @@ -96,6 +116,10 @@ export const moderationLogTypes = [ 'createAbuseReportNotificationRecipient', 'updateAbuseReportNotificationRecipient', 'deleteAbuseReportNotificationRecipient', + 'deleteAccount', + 'deletePage', + 'deleteFlash', + 'deleteGalleryPost', ] as const; export type ModerationLogPayloads = { @@ -245,7 +269,18 @@ export type ModerationLogPayloads = { resolveAbuseReport: { reportId: string; report: any; - forwarded: boolean; + forwarded?: boolean; + resolvedAs?: string | null; + }; + forwardAbuseReport: { + reportId: string; + report: any; + }; + updateAbuseReportNote: { + reportId: string; + report: any; + before: string; + after: string; }; createInvitation: { invitations: any[]; @@ -314,6 +349,29 @@ export type ModerationLogPayloads = { recipientId: string; recipient: any; }; + deleteAccount: { + userId: string; + userUsername: string; + userHost: string | null; + }; + deletePage: { + pageId: string; + pageUserId: string; + pageUserUsername: string; + page: any; + }; + deleteFlash: { + flashId: string; + flashUserId: string; + flashUserUsername: string; + flash: any; + }; + deleteGalleryPost: { + postId: string; + postUserId: string; + postUserUsername: string; + post: any; + }; }; export type Serialized = { diff --git a/packages/backend/test-server/.eslintrc.cjs b/packages/backend/test-server/.eslintrc.cjs deleted file mode 100644 index c261741a36..0000000000 --- a/packages/backend/test-server/.eslintrc.cjs +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../../shared/.eslintrc.js', - ], - rules: { - 'import/order': ['warn', { - 'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], - 'pathGroups': [ - { - 'pattern': '@/**', - 'group': 'external', - 'position': 'after' - } - ], - }], - 'no-restricted-globals': [ - 'error', - { - 'name': '__dirname', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - }, - { - 'name': '__filename', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - } - ] - }, -}; diff --git a/packages/backend/test-server/entry.ts b/packages/backend/test-server/entry.ts index 866a7e1f5b..04bf62d209 100644 --- a/packages/backend/test-server/entry.ts +++ b/packages/backend/test-server/entry.ts @@ -6,12 +6,16 @@ import { MainModule } from '@/MainModule.js'; import { ServerService } from '@/server/ServerService.js'; import { loadConfig } from '@/config.js'; import { NestLogger } from '@/NestLogger.js'; +import { INestApplicationContext } from '@nestjs/common'; const config = loadConfig(); const originEnv = JSON.stringify(process.env); process.env.NODE_ENV = 'test'; +let app: INestApplicationContext; +let serverService: ServerService; + /** * テスト用のサーバインスタンスを起動する */ @@ -20,10 +24,10 @@ async function launch() { console.log('starting application...'); - const app = await NestFactory.createApplicationContext(MainModule, { + app = await NestFactory.createApplicationContext(MainModule, { logger: new NestLogger(), }); - const serverService = app.get(ServerService); + serverService = app.get(ServerService); await serverService.launch(); await startControllerEndpoints(); @@ -71,6 +75,20 @@ async function startControllerEndpoints(port = config.port + 1000) { fastify.post<{ Body: { key?: string, value?: string } }>('/env-reset', async (req, res) => { process.env = JSON.parse(originEnv); + + await serverService.dispose(); + await app.close(); + + await killTestServer(); + + console.log('starting application...'); + + app = await NestFactory.createApplicationContext(MainModule, { + logger: new NestLogger(), + }); + serverService = app.get(ServerService); + await serverService.launch(); + res.code(200).send({ success: true }); }); diff --git a/packages/backend/test-server/eslint.config.js b/packages/backend/test-server/eslint.config.js new file mode 100644 index 0000000000..b9c16d469f --- /dev/null +++ b/packages/backend/test-server/eslint.config.js @@ -0,0 +1,43 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + 'import/order': ['warn', { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + 'type', + ], + pathGroups: [{ + pattern: '@/**', + group: 'external', + position: 'after', + }], + }], + 'no-restricted-globals': ['error', { + name: '__dirname', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }, { + name: '__filename', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }], + }, + }, +]; diff --git a/packages/backend/test/.eslintrc.cjs b/packages/backend/test/.eslintrc.cjs deleted file mode 100644 index 41ecea0c3f..0000000000 --- a/packages/backend/test/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: ['../.eslintrc.cjs'], - env: { - node: true, - jest: true, - }, -}; diff --git a/packages/backend/test/docker-compose.yml b/packages/backend/test/compose.yml similarity index 94% rename from packages/backend/test/docker-compose.yml rename to packages/backend/test/compose.yml index f2d8990758..6593fc33dd 100644 --- a/packages/backend/test/docker-compose.yml +++ b/packages/backend/test/compose.yml @@ -1,5 +1,3 @@ -version: "3" - services: redistest: image: redis:7 diff --git a/packages/backend/test/e2e/2fa.ts b/packages/backend/test/e2e/2fa.ts index 13c56b88a6..48e1bababb 100644 --- a/packages/backend/test/e2e/2fa.ts +++ b/packages/backend/test/e2e/2fa.ts @@ -136,13 +136,7 @@ describe('2要素認証', () => { keyName: string, credentialId: Buffer, requestOptions: PublicKeyCredentialRequestOptionsJSON, - }): { - username: string, - password: string, - credential: AuthenticationResponseJSON, - 'g-recaptcha-response'?: string | null, - 'hcaptcha-response'?: string | null, - } => { + }): misskey.entities.SigninFlowRequest => { // AuthenticatorAssertionResponse.authenticatorData // https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAssertionResponse/authenticatorData const authenticatorData = Buffer.concat([ @@ -202,17 +196,21 @@ describe('2要素認証', () => { }, alice); assert.strictEqual(doneResponse.status, 200); - const usersShowResponse = await api('users/show', { - username, - }, alice); - assert.strictEqual(usersShowResponse.status, 200); - assert.strictEqual(usersShowResponse.body.twoFactorEnabled, true); + const signinWithoutTokenResponse = await api('signin-flow', { + ...signinParam(), + }); + assert.strictEqual(signinWithoutTokenResponse.status, 200); + assert.deepStrictEqual(signinWithoutTokenResponse.body, { + finished: false, + next: 'totp', + }); - const signinResponse = await api('signin', { + const signinResponse = await api('signin-flow', { ...signinParam(), token: otpToken(registerResponse.body.secret), }); assert.strictEqual(signinResponse.status, 200); + assert.strictEqual(signinResponse.body.finished, true); assert.notEqual(signinResponse.body.i, undefined); // 後片付け @@ -248,32 +246,28 @@ describe('2要素認証', () => { keyName, credentialId, creationOptions: registerKeyResponse.body, - }) as any, alice); + } as any) as any, alice); assert.strictEqual(keyDoneResponse.status, 200); assert.strictEqual(keyDoneResponse.body.id, credentialId.toString('base64url')); assert.strictEqual(keyDoneResponse.body.name, keyName); - const usersShowResponse = await api('users/show', { - username, - }); - assert.strictEqual(usersShowResponse.status, 200); - assert.strictEqual(usersShowResponse.body.securityKeys, true); - - const signinResponse = await api('signin', { + const signinResponse = await api('signin-flow', { ...signinParam(), }); assert.strictEqual(signinResponse.status, 200); - assert.strictEqual(signinResponse.body.i, undefined); - assert.notEqual(signinResponse.body.challenge, undefined); - assert.notEqual(signinResponse.body.allowCredentials, undefined); - assert.strictEqual(signinResponse.body.allowCredentials[0].id, credentialId.toString('base64url')); + assert.strictEqual(signinResponse.body.finished, false); + assert.strictEqual(signinResponse.body.next, 'passkey'); + assert.notEqual(signinResponse.body.authRequest.challenge, undefined); + assert.notEqual(signinResponse.body.authRequest.allowCredentials, undefined); + assert.strictEqual(signinResponse.body.authRequest.allowCredentials && signinResponse.body.authRequest.allowCredentials[0]?.id, credentialId.toString('base64url')); - const signinResponse2 = await api('signin', signinWithSecurityKeyParam({ + const signinResponse2 = await api('signin-flow', signinWithSecurityKeyParam({ keyName, credentialId, - requestOptions: signinResponse.body, + requestOptions: signinResponse.body.authRequest, })); assert.strictEqual(signinResponse2.status, 200); + assert.strictEqual(signinResponse2.body.finished, true); assert.notEqual(signinResponse2.body.i, undefined); // 後片付け @@ -307,7 +301,7 @@ describe('2要素認証', () => { keyName, credentialId, creationOptions: registerKeyResponse.body, - }) as any, alice); + } as any) as any, alice); assert.strictEqual(keyDoneResponse.status, 200); const passwordLessResponse = await api('i/2fa/password-less', { @@ -315,28 +309,30 @@ describe('2要素認証', () => { }, alice); assert.strictEqual(passwordLessResponse.status, 204); - const usersShowResponse = await api('users/show', { - username, - }); - assert.strictEqual(usersShowResponse.status, 200); - assert.strictEqual(usersShowResponse.body.usePasswordLessLogin, true); + const iResponse = await api('i', {}, alice); + assert.strictEqual(iResponse.status, 200); + assert.strictEqual(iResponse.body.usePasswordLessLogin, true); - const signinResponse = await api('signin', { + const signinResponse = await api('signin-flow', { ...signinParam(), password: '', }); assert.strictEqual(signinResponse.status, 200); - assert.strictEqual(signinResponse.body.i, undefined); + assert.strictEqual(signinResponse.body.finished, false); + assert.strictEqual(signinResponse.body.next, 'passkey'); + assert.notEqual(signinResponse.body.authRequest.challenge, undefined); + assert.notEqual(signinResponse.body.authRequest.allowCredentials, undefined); - const signinResponse2 = await api('signin', { + const signinResponse2 = await api('signin-flow', { ...signinWithSecurityKeyParam({ keyName, credentialId, - requestOptions: signinResponse.body, - }), + requestOptions: signinResponse.body.authRequest, + } as any), password: '', }); assert.strictEqual(signinResponse2.status, 200); + assert.strictEqual(signinResponse2.body.finished, true); assert.notEqual(signinResponse2.body.i, undefined); // 後片付け @@ -370,7 +366,7 @@ describe('2要素認証', () => { keyName, credentialId, creationOptions: registerKeyResponse.body, - }) as any, alice); + } as any) as any, alice); assert.strictEqual(keyDoneResponse.status, 200); const renamedKey = 'other-key'; @@ -383,6 +379,7 @@ describe('2要素認証', () => { const iResponse = await api('i', { }, alice); assert.strictEqual(iResponse.status, 200); + assert.ok(iResponse.body.securityKeysList); const securityKeys = iResponse.body.securityKeysList.filter((s: { id: string; }) => s.id === credentialId.toString('base64url')); assert.strictEqual(securityKeys.length, 1); assert.strictEqual(securityKeys[0].name, renamedKey); @@ -419,14 +416,15 @@ describe('2要素認証', () => { keyName, credentialId, creationOptions: registerKeyResponse.body, - }) as any, alice); + } as any) as any, alice); assert.strictEqual(keyDoneResponse.status, 200); // テストの実行順によっては複数残ってるので全部消す - const iResponse = await api('i', { + const beforeIResponse = await api('i', { }, alice); - assert.strictEqual(iResponse.status, 200); - for (const key of iResponse.body.securityKeysList) { + assert.strictEqual(beforeIResponse.status, 200); + assert.ok(beforeIResponse.body.securityKeysList); + for (const key of beforeIResponse.body.securityKeysList) { const removeKeyResponse = await api('i/2fa/remove-key', { token: otpToken(registerResponse.body.secret), password, @@ -435,17 +433,16 @@ describe('2要素認証', () => { assert.strictEqual(removeKeyResponse.status, 200); } - const usersShowResponse = await api('users/show', { - username, - }); - assert.strictEqual(usersShowResponse.status, 200); - assert.strictEqual(usersShowResponse.body.securityKeys, false); + const afterIResponse = await api('i', {}, alice); + assert.strictEqual(afterIResponse.status, 200); + assert.strictEqual(afterIResponse.body.securityKeys, false); - const signinResponse = await api('signin', { + const signinResponse = await api('signin-flow', { ...signinParam(), token: otpToken(registerResponse.body.secret), }); assert.strictEqual(signinResponse.status, 200); + assert.strictEqual(signinResponse.body.finished, true); assert.notEqual(signinResponse.body.i, undefined); // 後片付け @@ -466,11 +463,9 @@ describe('2要素認証', () => { }, alice); assert.strictEqual(doneResponse.status, 200); - const usersShowResponse = await api('users/show', { - username, - }); - assert.strictEqual(usersShowResponse.status, 200); - assert.strictEqual(usersShowResponse.body.twoFactorEnabled, true); + const iResponse = await api('i', {}, alice); + assert.strictEqual(iResponse.status, 200); + assert.strictEqual(iResponse.body.twoFactorEnabled, true); const unregisterResponse = await api('i/2fa/unregister', { token: otpToken(registerResponse.body.secret), @@ -478,10 +473,11 @@ describe('2要素認証', () => { }, alice); assert.strictEqual(unregisterResponse.status, 204); - const signinResponse = await api('signin', { + const signinResponse = await api('signin-flow', { ...signinParam(), }); assert.strictEqual(signinResponse.status, 200); + assert.strictEqual(signinResponse.body.finished, true); assert.notEqual(signinResponse.body.i, undefined); // 後片付け diff --git a/packages/backend/test/e2e/antennas.ts b/packages/backend/test/e2e/antennas.ts index 6ac14cd8dc..a544db955a 100644 --- a/packages/backend/test/e2e/antennas.ts +++ b/packages/backend/test/e2e/antennas.ts @@ -228,6 +228,17 @@ describe('アンテナ', () => { assert.deepStrictEqual(response, expected); }); + test('を作成する時キーワードが指定されていないとエラーになる', async () => { + await failedApiCall({ + endpoint: 'antennas/create', + parameters: { ...defaultParam, keywords: [[]], excludeKeywords: [[]] }, + user: alice + }, { + status: 400, + code: 'EMPTY_KEYWORD', + id: '53ee222e-1ddd-4f9a-92e5-9fb82ddb463a' + }) + }); //#endregion //#region 更新(antennas/update) @@ -255,6 +266,18 @@ describe('アンテナ', () => { id: '1c6b35c9-943e-48c2-81e4-2844989407f7', }); }); + test('を変更する時キーワードが指定されていないとエラーになる', async () => { + const antenna = await successfulApiCall({ endpoint: 'antennas/create', parameters: defaultParam, user: alice }); + await failedApiCall({ + endpoint: 'antennas/update', + parameters: { ...defaultParam, antennaId: antenna.id, keywords: [[]], excludeKeywords: [[]] }, + user: alice + }, { + status: 400, + code: 'EMPTY_KEYWORD', + id: '721aaff6-4e1b-4d88-8de6-877fae9f68c4' + }) + }); //#endregion //#region 表示(antennas/show) diff --git a/packages/backend/test/e2e/api-visibility.ts b/packages/backend/test/e2e/api-visibility.ts index c61b0c2a86..2dd645d97a 100644 --- a/packages/backend/test/e2e/api-visibility.ts +++ b/packages/backend/test/e2e/api-visibility.ts @@ -410,21 +410,21 @@ describe('API visibility', () => { test('[HTL] public-post が 自分が見れる', async () => { const res = await api('notes/timeline', { limit: 100 }, alice); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === pub.id); + const notes = res.body.filter(n => n.id === pub.id); assert.strictEqual(notes[0].text, 'x'); }); test('[HTL] public-post が 非フォロワーから見れない', async () => { const res = await api('notes/timeline', { limit: 100 }, other); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === pub.id); + const notes = res.body.filter(n => n.id === pub.id); assert.strictEqual(notes.length, 0); }); test('[HTL] followers-post が フォロワーから見れる', async () => { const res = await api('notes/timeline', { limit: 100 }, follower); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === fol.id); + const notes = res.body.filter(n => n.id === fol.id); assert.strictEqual(notes[0].text, 'x'); }); //#endregion @@ -433,21 +433,21 @@ describe('API visibility', () => { test('[replies] followers-reply が フォロワーから見れる', async () => { const res = await api('notes/replies', { noteId: tgt.id, limit: 100 }, follower); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === folR.id); + const notes = res.body.filter(n => n.id === folR.id); assert.strictEqual(notes[0].text, 'x'); }); test('[replies] followers-reply が 非フォロワー (リプライ先ではない) から見れない', async () => { const res = await api('notes/replies', { noteId: tgt.id, limit: 100 }, other); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === folR.id); + const notes = res.body.filter(n => n.id === folR.id); assert.strictEqual(notes.length, 0); }); test('[replies] followers-reply が 非フォロワー (リプライ先である) から見れる', async () => { const res = await api('notes/replies', { noteId: tgt.id, limit: 100 }, target); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === folR.id); + const notes = res.body.filter(n => n.id === folR.id); assert.strictEqual(notes[0].text, 'x'); }); //#endregion @@ -456,14 +456,14 @@ describe('API visibility', () => { test('[mentions] followers-reply が 非フォロワー (リプライ先である) から見れる', async () => { const res = await api('notes/mentions', { limit: 100 }, target); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === folR.id); + const notes = res.body.filter(n => n.id === folR.id); assert.strictEqual(notes[0].text, 'x'); }); test('[mentions] followers-mention が 非フォロワー (メンション先である) から見れる', async () => { const res = await api('notes/mentions', { limit: 100 }, target); assert.strictEqual(res.status, 200); - const notes = res.body.filter((n: any) => n.id === folM.id); + const notes = res.body.filter(n => n.id === folM.id); assert.strictEqual(notes[0].text, '@target x'); }); //#endregion diff --git a/packages/backend/test/e2e/block.ts b/packages/backend/test/e2e/block.ts index e4f798498f..35b0e59383 100644 --- a/packages/backend/test/e2e/block.ts +++ b/packages/backend/test/e2e/block.ts @@ -6,7 +6,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; -import { api, post, signup } from '../utils.js'; +import { api, castAsError, post, signup } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Block', () => { @@ -33,7 +33,7 @@ describe('Block', () => { const res = await api('following/create', { userId: alice.id }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.id, 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0'); + assert.strictEqual(castAsError(res.body).error.id, 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0'); }); test('ブロックされているユーザーにリアクションできない', async () => { @@ -42,7 +42,8 @@ describe('Block', () => { const res = await api('notes/reactions/create', { noteId: note.id, reaction: '👍' }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.id, '20ef5475-9f38-4e4c-bd33-de6d979498ec'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.id, '20ef5475-9f38-4e4c-bd33-de6d979498ec'); }); test('ブロックされているユーザーに返信できない', async () => { @@ -51,7 +52,8 @@ describe('Block', () => { const res = await api('notes/create', { replyId: note.id, text: 'yo' }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3'); }); test('ブロックされているユーザーのノートをRenoteできない', async () => { @@ -60,7 +62,7 @@ describe('Block', () => { const res = await api('notes/create', { renoteId: note.id, text: 'yo' }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3'); + assert.strictEqual(castAsError(res.body).error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3'); }); // TODO: ユーザーリストに入れられないテスト diff --git a/packages/backend/test/e2e/clips.ts b/packages/backend/test/e2e/clips.ts index a229ec06f9..a130c3698d 100644 --- a/packages/backend/test/e2e/clips.ts +++ b/packages/backend/test/e2e/clips.ts @@ -79,14 +79,14 @@ describe('クリップ', () => { }; const deleteClip = async (parameters: Misskey.entities.ClipsDeleteRequest, request: Partial> = {}): Promise => { - return await successfulApiCall({ + await successfulApiCall({ endpoint: 'clips/delete', parameters, user: alice, ...request, }, { status: 204, - }) as any as void; + }); }; const show = async (parameters: Misskey.entities.ClipsShowRequest, request: Partial> = {}): Promise => { @@ -454,25 +454,25 @@ describe('クリップ', () => { let aliceClip: Misskey.entities.Clip; const favorite = async (parameters: Misskey.entities.ClipsFavoriteRequest, request: Partial> = {}): Promise => { - return successfulApiCall({ + await successfulApiCall({ endpoint: 'clips/favorite', parameters, user: alice, ...request, }, { status: 204, - }) as any as void; + }); }; const unfavorite = async (parameters: Misskey.entities.ClipsUnfavoriteRequest, request: Partial> = {}): Promise => { - return successfulApiCall({ + await successfulApiCall({ endpoint: 'clips/unfavorite', parameters, user: alice, ...request, }, { status: 204, - }) as any as void; + }); }; const myFavorites = async (request: Partial> = {}): Promise => { diff --git a/packages/backend/test/e2e/drive.ts b/packages/backend/test/e2e/drive.ts index 828c5200ef..43a73163eb 100644 --- a/packages/backend/test/e2e/drive.ts +++ b/packages/backend/test/e2e/drive.ts @@ -23,7 +23,7 @@ describe('Drive', () => { const marker = Math.random().toString(); - const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'; + const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'; const catcher = makeStreamCatcher( alice, @@ -41,14 +41,14 @@ describe('Drive', () => { const file = await catcher; assert.strictEqual(res.status, 204); - assert.strictEqual(file.name, 'Lenna.jpg'); + assert.strictEqual(file.name, '192.jpg'); assert.strictEqual(file.type, 'image/jpeg'); }); test('ローカルからアップロードできる', async () => { // APIレスポンスを直接使用するので utils.js uploadFile が通過することで成功とする - const res = await uploadFile(alice, { path: 'Lenna.jpg', name: 'テスト画像' }); + const res = await uploadFile(alice, { path: '192.jpg', name: 'テスト画像' }); assert.strictEqual(res.body?.name, 'テスト画像.jpg'); assert.strictEqual(res.body.type, 'image/jpeg'); diff --git a/packages/backend/test/e2e/endpoints.ts b/packages/backend/test/e2e/endpoints.ts index de5e8ba95e..b91d77c398 100644 --- a/packages/backend/test/e2e/endpoints.ts +++ b/packages/backend/test/e2e/endpoints.ts @@ -10,7 +10,7 @@ import * as assert from 'assert'; // https://github.com/node-fetch/node-fetch/pull/1664 import { Blob } from 'node-fetch'; import { MiUser } from '@/models/_.js'; -import { api, initTestDb, post, signup, simpleGet, uploadFile } from '../utils.js'; +import { api, castAsError, initTestDb, post, signup, simpleGet, uploadFile } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Endpoints', () => { @@ -66,9 +66,9 @@ describe('Endpoints', () => { }); }); - describe('signin', () => { + describe('signin-flow', () => { test('間違ったパスワードでサインインできない', async () => { - const res = await api('signin', { + const res = await api('signin-flow', { username: 'test1', password: 'bar', }); @@ -77,7 +77,7 @@ describe('Endpoints', () => { }); test('クエリをインジェクションできない', async () => { - const res = await api('signin', { + const res = await api('signin-flow', { username: 'test1', // @ts-expect-error password must be string password: { @@ -89,7 +89,7 @@ describe('Endpoints', () => { }); test('正しい情報でサインインできる', async () => { - const res = await api('signin', { + const res = await api('signin-flow', { username: 'test1', password: 'test1', }); @@ -117,12 +117,21 @@ describe('Endpoints', () => { assert.strictEqual(res.body.birthday, myBirthday); }); - test('名前を空白にできる', async () => { + test('名前を空白のみにした場合nullになる', async () => { const res = await api('i/update', { name: ' ', }, alice); assert.strictEqual(res.status, 200); - assert.strictEqual(res.body.name, ' '); + assert.strictEqual(res.body.name, null); + }); + + test('名前の前後に空白(ホワイトスペース)を入れてもトリムされる', async () => { + const res = await api('i/update', { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#white_space + name: ' あ い う \u0009\u000b\u000c\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff', + }, alice); + assert.strictEqual(res.status, 200); + assert.strictEqual(res.body.name, 'あ い う'); }); test('誕生日の設定を削除できる', async () => { @@ -155,7 +164,7 @@ describe('Endpoints', () => { assert.strictEqual(res.status, 200); assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.id, alice.id); + assert.strictEqual((res.body as unknown as { id: string }).id, alice.id); }); test('ユーザーが存在しなかったら怒る', async () => { @@ -276,7 +285,8 @@ describe('Endpoints', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'CANNOT_REACT_TO_RENOTE'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.code, 'CANNOT_REACT_TO_RENOTE'); }); test('引用にリアクションできる', async () => { @@ -584,7 +594,7 @@ describe('Endpoints', () => { assert.strictEqual(res.status, 200); assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body!.name, 'Lenna.jpg'); + assert.strictEqual(res.body!.name, '192.jpg'); }); test('ファイルに名前を付けられる', async () => { @@ -1054,7 +1064,7 @@ describe('Endpoints', () => { userId: bob.id, }, alice); assert.strictEqual(res1.status, 204); - assert.strictEqual(res2.body?.memo, memo); + assert.strictEqual((res2.body as unknown as { memo: string })?.memo, memo); }); test('自分に関するメモを更新できる', async () => { @@ -1069,7 +1079,7 @@ describe('Endpoints', () => { userId: alice.id, }, alice); assert.strictEqual(res1.status, 204); - assert.strictEqual(res2.body?.memo, memo); + assert.strictEqual((res2.body as unknown as { memo: string })?.memo, memo); }); test('メモを削除できる', async () => { @@ -1090,7 +1100,7 @@ describe('Endpoints', () => { }, alice); // memoには常に文字列かnullが入っている(5cac151) - assert.strictEqual(res.body.memo, null); + assert.strictEqual((res.body as unknown as { memo: string | null }).memo, null); }); test('メモは個人ごとに独立して保存される', async () => { @@ -1117,8 +1127,8 @@ describe('Endpoints', () => { }, carol), ]); - assert.strictEqual(resAlice.body.memo, memoAliceToBob); - assert.strictEqual(resCarol.body.memo, memoCarolToBob); + assert.strictEqual((resAlice.body as unknown as { memo: string }).memo, memoAliceToBob); + assert.strictEqual((resCarol.body as unknown as { memo: string }).memo, memoCarolToBob); }); }); }); diff --git a/packages/backend/test/e2e/exports.ts b/packages/backend/test/e2e/exports.ts index 80a5331a6d..4bcecc9716 100644 --- a/packages/backend/test/e2e/exports.ts +++ b/packages/backend/test/e2e/exports.ts @@ -61,14 +61,14 @@ describe('export-clips', () => { }); test('basic export', async () => { - let res = await api('clips/create', { + const res1 = await api('clips/create', { name: 'foo', description: 'bar', }, alice); - assert.strictEqual(res.status, 200); + assert.strictEqual(res1.status, 200); - res = await api('i/export-clips', {}, alice); - assert.strictEqual(res.status, 204); + const res2 = await api('i/export-clips', {}, alice); + assert.strictEqual(res2.status, 204); const exported = await pollFirstDriveFile(); assert.strictEqual(exported[0].name, 'foo'); @@ -77,7 +77,7 @@ describe('export-clips', () => { }); test('export with notes', async () => { - let res = await api('clips/create', { + const res = await api('clips/create', { name: 'foo', description: 'bar', }, alice); @@ -96,15 +96,15 @@ describe('export-clips', () => { }); for (const note of [note1, note2]) { - res = await api('clips/add-note', { + const res2 = await api('clips/add-note', { clipId: clip.id, noteId: note.id, }, alice); - assert.strictEqual(res.status, 204); + assert.strictEqual(res2.status, 204); } - res = await api('i/export-clips', {}, alice); - assert.strictEqual(res.status, 204); + const res3 = await api('i/export-clips', {}, alice); + assert.strictEqual(res3.status, 204); const exported = await pollFirstDriveFile(); assert.strictEqual(exported[0].name, 'foo'); @@ -116,19 +116,19 @@ describe('export-clips', () => { }); test('multiple clips', async () => { - let res = await api('clips/create', { + const res1 = await api('clips/create', { name: 'kawaii', description: 'kawaii', }, alice); - assert.strictEqual(res.status, 200); - const clip1 = res.body; + assert.strictEqual(res1.status, 200); + const clip1 = res1.body; - res = await api('clips/create', { + const res2 = await api('clips/create', { name: 'yuri', description: 'yuri', }, alice); - assert.strictEqual(res.status, 200); - const clip2 = res.body; + assert.strictEqual(res2.status, 200); + const clip2 = res2.body; const note1 = await post(alice, { text: 'baz1', @@ -138,20 +138,26 @@ describe('export-clips', () => { text: 'baz2', }); - res = await api('clips/add-note', { - clipId: clip1.id, - noteId: note1.id, - }, alice); - assert.strictEqual(res.status, 204); + { + const res = await api('clips/add-note', { + clipId: clip1.id, + noteId: note1.id, + }, alice); + assert.strictEqual(res.status, 204); + } - res = await api('clips/add-note', { - clipId: clip2.id, - noteId: note2.id, - }, alice); - assert.strictEqual(res.status, 204); + { + const res = await api('clips/add-note', { + clipId: clip2.id, + noteId: note2.id, + }, alice); + assert.strictEqual(res.status, 204); + } - res = await api('i/export-clips', {}, alice); - assert.strictEqual(res.status, 204); + { + const res = await api('i/export-clips', {}, alice); + assert.strictEqual(res.status, 204); + } const exported = await pollFirstDriveFile(); assert.strictEqual(exported[0].name, 'kawaii'); @@ -163,7 +169,7 @@ describe('export-clips', () => { }); test('Clipping other user\'s note', async () => { - let res = await api('clips/create', { + const res = await api('clips/create', { name: 'kawaii', description: 'kawaii', }, alice); @@ -175,14 +181,14 @@ describe('export-clips', () => { visibility: 'followers', }); - res = await api('clips/add-note', { + const res2 = await api('clips/add-note', { clipId: clip.id, noteId: note.id, }, alice); - assert.strictEqual(res.status, 204); + assert.strictEqual(res2.status, 204); - res = await api('i/export-clips', {}, alice); - assert.strictEqual(res.status, 204); + const res3 = await api('i/export-clips', {}, alice); + assert.strictEqual(res3.status, 204); const exported = await pollFirstDriveFile(); assert.strictEqual(exported[0].name, 'kawaii'); diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index 74cf61a785..fd798bdb25 100644 --- a/packages/backend/test/e2e/move.ts +++ b/packages/backend/test/e2e/move.ts @@ -7,19 +7,20 @@ import { INestApplicationContext } from '@nestjs/common'; process.env.NODE_ENV = 'test'; +import { setTimeout } from 'node:timers/promises'; import * as assert from 'assert'; import { loadConfig } from '@/config.js'; import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { jobQueue } from '@/boot/common.js'; -import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js'; +import { api, castAsError, initTestDb, signup, successfulApiCall, uploadFile } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Account Move', () => { let jq: INestApplicationContext; let url: URL; - let root: any; + let root: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse; @@ -92,8 +93,8 @@ describe('Account Move', () => { }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_USER'); - assert.strictEqual(res.body.error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_USER'); + assert.strictEqual(castAsError(res.body).error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); }); test('Unable to add duplicated aliases to alsoKnownAs', async () => { @@ -102,8 +103,8 @@ describe('Account Move', () => { }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'INVALID_PARAM'); - assert.strictEqual(res.body.error.id, '3d81ceae-475f-4600-b2a8-2bc116157532'); + assert.strictEqual(castAsError(res.body).error.code, 'INVALID_PARAM'); + assert.strictEqual(castAsError(res.body).error.id, '3d81ceae-475f-4600-b2a8-2bc116157532'); }); test('Unable to add itself', async () => { @@ -112,8 +113,8 @@ describe('Account Move', () => { }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'FORBIDDEN_TO_SET_YOURSELF'); - assert.strictEqual(res.body.error.id, '25c90186-4ab0-49c8-9bba-a1fa6c202ba4'); + assert.strictEqual(castAsError(res.body).error.code, 'FORBIDDEN_TO_SET_YOURSELF'); + assert.strictEqual(castAsError(res.body).error.id, '25c90186-4ab0-49c8-9bba-a1fa6c202ba4'); }); test('Unable to add a nonexisting local account to alsoKnownAs', async () => { @@ -122,16 +123,16 @@ describe('Account Move', () => { }, bob); assert.strictEqual(res1.status, 400); - assert.strictEqual(res1.body.error.code, 'NO_SUCH_USER'); - assert.strictEqual(res1.body.error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); + assert.strictEqual(castAsError(res1.body).error.code, 'NO_SUCH_USER'); + assert.strictEqual(castAsError(res1.body).error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); const res2 = await api('i/update', { alsoKnownAs: ['@alice', 'nonexist'], }, bob); assert.strictEqual(res2.status, 400); - assert.strictEqual(res2.body.error.code, 'NO_SUCH_USER'); - assert.strictEqual(res2.body.error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); + assert.strictEqual(castAsError(res2.body).error.code, 'NO_SUCH_USER'); + assert.strictEqual(castAsError(res2.body).error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); }); test('Able to add two existing local account to alsoKnownAs', async () => { @@ -240,8 +241,8 @@ describe('Account Move', () => { }, root); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NOT_ROOT_FORBIDDEN'); - assert.strictEqual(res.body.error.id, '4362e8dc-731f-4ad8-a694-be2a88922a24'); + assert.strictEqual(castAsError(res.body).error.code, 'NOT_ROOT_FORBIDDEN'); + assert.strictEqual(castAsError(res.body).error.id, '4362e8dc-731f-4ad8-a694-be2a88922a24'); }); test('Unable to move to a nonexisting local account', async () => { @@ -250,8 +251,8 @@ describe('Account Move', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_USER'); - assert.strictEqual(res.body.error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_USER'); + assert.strictEqual(castAsError(res.body).error.id, 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'); }); test('Unable to move if alsoKnownAs is invalid', async () => { @@ -260,8 +261,8 @@ describe('Account Move', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'DESTINATION_ACCOUNT_FORBIDS'); - assert.strictEqual(res.body.error.id, 'b5c90186-4ab0-49c8-9bba-a1f766282ba4'); + assert.strictEqual(castAsError(res.body).error.code, 'DESTINATION_ACCOUNT_FORBIDS'); + assert.strictEqual(castAsError(res.body).error.id, 'b5c90186-4ab0-49c8-9bba-a1f766282ba4'); }); test('Relationships have been properly migrated', async () => { @@ -271,43 +272,51 @@ describe('Account Move', () => { assert.strictEqual(move.status, 200); - await sleep(1000 * 3); // wait for jobs to finish + await setTimeout(1000 * 3); // wait for jobs to finish // Unfollow delayed? const aliceFollowings = await api('users/following', { userId: alice.id, }, alice); assert.strictEqual(aliceFollowings.status, 200); + assert.ok(aliceFollowings); assert.strictEqual(aliceFollowings.body.length, 3); const carolFollowings = await api('users/following', { userId: carol.id, }, carol); assert.strictEqual(carolFollowings.status, 200); + assert.ok(carolFollowings); assert.strictEqual(carolFollowings.body.length, 2); assert.strictEqual(carolFollowings.body[0].followeeId, bob.id); assert.strictEqual(carolFollowings.body[1].followeeId, alice.id); const blockings = await api('blocking/list', {}, dave); assert.strictEqual(blockings.status, 200); + assert.ok(blockings); assert.strictEqual(blockings.body.length, 2); assert.strictEqual(blockings.body[0].blockeeId, bob.id); assert.strictEqual(blockings.body[1].blockeeId, alice.id); const mutings = await api('mute/list', {}, dave); assert.strictEqual(mutings.status, 200); + assert.ok(mutings); assert.strictEqual(mutings.body.length, 2); assert.strictEqual(mutings.body[0].muteeId, bob.id); assert.strictEqual(mutings.body[1].muteeId, alice.id); const rootLists = await api('users/lists/list', {}, root); assert.strictEqual(rootLists.status, 200); + assert.ok(rootLists); + assert.ok(rootLists.body[0].userIds); assert.strictEqual(rootLists.body[0].userIds.length, 2); assert.ok(rootLists.body[0].userIds.find((id: string) => id === bob.id)); assert.ok(rootLists.body[0].userIds.find((id: string) => id === alice.id)); const eveLists = await api('users/lists/list', {}, eve); assert.strictEqual(eveLists.status, 200); + assert.ok(eveLists); + assert.ok(eveLists.body[0].userIds); assert.strictEqual(eveLists.body[0].userIds.length, 1); assert.ok(eveLists.body[0].userIds.find((id: string) => id === bob.id)); }); @@ -330,7 +339,7 @@ describe('Account Move', () => { }); test('Unfollowed after 10 sec (24 hours in production).', async () => { - await sleep(1000 * 8); + await setTimeout(1000 * 8); const following = await api('users/following', { userId: alice.id, @@ -346,8 +355,8 @@ describe('Account Move', () => { }, bob); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'DESTINATION_ACCOUNT_FORBIDS'); - assert.strictEqual(res.body.error.id, 'b5c90186-4ab0-49c8-9bba-a1f766282ba4'); + assert.strictEqual(castAsError(res.body).error.code, 'DESTINATION_ACCOUNT_FORBIDS'); + assert.strictEqual(castAsError(res.body).error.id, 'b5c90186-4ab0-49c8-9bba-a1f766282ba4'); }); test('Follow and follower counts are properly adjusted', async () => { @@ -418,8 +427,9 @@ describe('Account Move', () => { ] as const)('Prohibit access after moving: %s', async (endpoint) => { const res = await api(endpoint, {}, alice); assert.strictEqual(res.status, 403); - assert.strictEqual(res.body.error.code, 'YOUR_ACCOUNT_MOVED'); - assert.strictEqual(res.body.error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.code, 'YOUR_ACCOUNT_MOVED'); + assert.strictEqual(castAsError(res.body).error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); }); test('Prohibit access after moving: /antennas/update', async () => { @@ -437,16 +447,19 @@ describe('Account Move', () => { }, alice); assert.strictEqual(res.status, 403); - assert.strictEqual(res.body.error.code, 'YOUR_ACCOUNT_MOVED'); - assert.strictEqual(res.body.error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.code, 'YOUR_ACCOUNT_MOVED'); + assert.strictEqual(castAsError(res.body).error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); }); test('Prohibit access after moving: /drive/files/create', async () => { + // FIXME: 一旦逃げておく const res = await uploadFile(alice); assert.strictEqual(res.status, 403); - assert.strictEqual((res.body! as any as { error: misskey.api.APIError }).error.code, 'YOUR_ACCOUNT_MOVED'); - assert.strictEqual((res.body! as any as { error: misskey.api.APIError }).error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); + assert.ok(res.body); + assert.strictEqual(castAsError(res.body).error.code, 'YOUR_ACCOUNT_MOVED'); + assert.strictEqual(castAsError(res.body).error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); }); test('Prohibit updating alsoKnownAs after moving', async () => { @@ -455,8 +468,8 @@ describe('Account Move', () => { }, alice); assert.strictEqual(res.status, 403); - assert.strictEqual(res.body.error.code, 'YOUR_ACCOUNT_MOVED'); - assert.strictEqual(res.body.error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); + assert.strictEqual(castAsError(res.body).error.code, 'YOUR_ACCOUNT_MOVED'); + assert.strictEqual(castAsError(res.body).error.id, '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31'); }); }); }); diff --git a/packages/backend/test/e2e/mute.ts b/packages/backend/test/e2e/mute.ts index 0e52c5decc..f37da288b7 100644 --- a/packages/backend/test/e2e/mute.ts +++ b/packages/backend/test/e2e/mute.ts @@ -47,8 +47,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test('ミュートしているユーザーからメンションされても、hasUnreadMentions が true にならない', async () => { @@ -92,9 +92,9 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test('タイムラインにミュートしているユーザーの投稿のRenoteが含まれない', async () => { @@ -108,9 +108,9 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); }); @@ -124,8 +124,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリプライが含まれない', async () => { @@ -138,8 +138,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリプライが含まれない', async () => { @@ -152,8 +152,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからの引用リノートが含まれない', async () => { @@ -166,8 +166,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリノートが含まれない', async () => { @@ -180,8 +180,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのフォロー通知が含まれない', async () => { @@ -193,8 +193,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); await api('following/delete', { userId: alice.id }, bob); await api('following/delete', { userId: alice.id }, carol); @@ -210,8 +210,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); await api('following/delete', { userId: alice.id }, bob); await api('following/delete', { userId: alice.id }, carol); @@ -228,8 +228,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリプライが含まれない', async () => { const aliceNote = await post(alice, { text: 'hi' }); @@ -241,8 +241,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリプライが含まれない', async () => { @@ -255,8 +255,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからの引用リノートが含まれない', async () => { @@ -269,8 +269,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのリノートが含まれない', async () => { @@ -283,8 +283,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); test('通知にミュートしているユーザーからのフォロー通知が含まれない', async () => { @@ -296,8 +296,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); await api('following/delete', { userId: alice.id }, bob); await api('following/delete', { userId: alice.id }, carol); @@ -313,8 +313,8 @@ describe('Mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true); - assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === bob.id), true); + assert.strictEqual(res.body.some(notification => 'userId' in notification && notification.userId === carol.id), false); }); }); }); diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts index bda31d9640..5937eb9b49 100644 --- a/packages/backend/test/e2e/note.ts +++ b/packages/backend/test/e2e/note.ts @@ -3,16 +3,18 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import type { Repository } from "typeorm"; + process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import { MiNote } from '@/models/Note.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; -import { api, initTestDb, post, role, signup, uploadFile, uploadUrl } from '../utils.js'; +import { api, castAsError, initTestDb, post, role, signup, uploadFile, uploadUrl } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Note', () => { - let Notes: any; + let Notes: Repository; let root: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse; @@ -41,7 +43,7 @@ describe('Note', () => { }); test('ファイルを添付できる', async () => { - const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); + const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); const res = await api('notes/create', { fileIds: [file.id], @@ -53,7 +55,7 @@ describe('Note', () => { }, 1000 * 10); test('他人のファイルで怒られる', async () => { - const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); + const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); const res = await api('notes/create', { text: 'test', @@ -61,8 +63,8 @@ describe('Note', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE'); - assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_FILE'); + assert.strictEqual(castAsError(res.body).error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); }, 1000 * 10); test('存在しないファイルで怒られる', async () => { @@ -72,8 +74,8 @@ describe('Note', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE'); - assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_FILE'); + assert.strictEqual(castAsError(res.body).error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); }); test('不正なファイルIDで怒られる', async () => { @@ -81,8 +83,8 @@ describe('Note', () => { fileIds: ['kyoppie'], }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE'); - assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_FILE'); + assert.strictEqual(castAsError(res.body).error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306'); }); test('返信できる', async () => { @@ -101,6 +103,7 @@ describe('Note', () => { assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); assert.strictEqual(res.body.createdNote.text, alicePost.text); assert.strictEqual(res.body.createdNote.replyId, alicePost.replyId); + assert.ok(res.body.createdNote.reply); assert.strictEqual(res.body.createdNote.reply.text, bobPost.text); }); @@ -118,6 +121,7 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); assert.strictEqual(res.body.createdNote.renoteId, alicePost.renoteId); + assert.ok(res.body.createdNote.renote); assert.strictEqual(res.body.createdNote.renote.text, bobPost.text); }); @@ -137,6 +141,7 @@ describe('Note', () => { assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); assert.strictEqual(res.body.createdNote.text, alicePost.text); assert.strictEqual(res.body.createdNote.renoteId, alicePost.renoteId); + assert.ok(res.body.createdNote.renote); assert.strictEqual(res.body.createdNote.renote.text, bobPost.text); }); @@ -218,7 +223,7 @@ describe('Note', () => { }, bob); assert.strictEqual(bobReply.status, 400); - assert.strictEqual(bobReply.body.error.code, 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE'); + assert.strictEqual(castAsError(bobReply.body).error.code, 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE'); }); test('visibility: specifiedなノートに対してvisibility: specifiedで返信できる', async () => { @@ -256,7 +261,7 @@ describe('Note', () => { }, bob); assert.strictEqual(bobReply.status, 400); - assert.strictEqual(bobReply.body.error.code, 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY'); + assert.strictEqual(castAsError(bobReply.body).error.code, 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY'); }); test('文字数ぎりぎりで怒られない', async () => { @@ -333,6 +338,7 @@ describe('Note', () => { assert.strictEqual(res.body.createdNote.text, post.text); const noteDoc = await Notes.findOneBy({ id: res.body.createdNote.id }); + assert.ok(noteDoc); assert.deepStrictEqual(noteDoc.mentions, [bob.id]); }); @@ -345,6 +351,7 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.ok(res.body.createdNote.files); assert.strictEqual(res.body.createdNote.files.length, 1); assert.strictEqual(res.body.createdNote.files[0].id, file.body!.id); }); @@ -363,8 +370,9 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - const myNote = res.body.find((note: { id: string; files: { id: string }[] }) => note.id === createdNote.body.createdNote.id); - assert.notEqual(myNote, null); + const myNote = res.body.find(note => note.id === createdNote.body.createdNote.id); + assert.ok(myNote); + assert.ok(myNote.files); assert.strictEqual(myNote.files.length, 1); assert.strictEqual(myNote.files[0].id, file.body!.id); }); @@ -389,7 +397,9 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); const myNote = res.body.find((note: { id: string }) => note.id === renoted.body.createdNote.id); - assert.notEqual(myNote, null); + assert.ok(myNote); + assert.ok(myNote.renote); + assert.ok(myNote.renote.files); assert.strictEqual(myNote.renote.files.length, 1); assert.strictEqual(myNote.renote.files[0].id, file.body!.id); }); @@ -415,7 +425,9 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); const myNote = res.body.find((note: { id: string }) => note.id === reply.body.createdNote.id); - assert.notEqual(myNote, null); + assert.ok(myNote); + assert.ok(myNote.reply); + assert.ok(myNote.reply.files); assert.strictEqual(myNote.reply.files.length, 1); assert.strictEqual(myNote.reply.files[0].id, file.body!.id); }); @@ -446,7 +458,10 @@ describe('Note', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); const myNote = res.body.find((note: { id: string }) => note.id === renoted.body.createdNote.id); - assert.notEqual(myNote, null); + assert.ok(myNote); + assert.ok(myNote.renote); + assert.ok(myNote.renote.reply); + assert.ok(myNote.renote.reply.files); assert.strictEqual(myNote.renote.reply.files.length, 1); assert.strictEqual(myNote.renote.reply.files[0].id, file.body!.id); }); @@ -474,7 +489,7 @@ describe('Note', () => { priority: 0, value: true, }, - } as any, + }, }, root); assert.strictEqual(res.status, 200); @@ -498,7 +513,7 @@ describe('Note', () => { }, alice); assert.strictEqual(liftnsfw.status, 400); - assert.strictEqual(liftnsfw.body.error.code, 'RESTRICTED_BY_ROLE'); + assert.strictEqual(castAsError(liftnsfw.body).error.code, 'RESTRICTED_BY_ROLE'); const oldaddnsfw = await api('drive/files/update', { fileId: file.body!.id, @@ -710,7 +725,7 @@ describe('Note', () => { }, alice); assert.strictEqual(note1.status, 400); - assert.strictEqual(note1.body.error.code, 'CONTAINS_PROHIBITED_WORDS'); + assert.strictEqual(castAsError(note1.body).error.code, 'CONTAINS_PROHIBITED_WORDS'); }); test('禁止ワードを含む投稿はエラーになる (正規表現)', async () => { @@ -727,7 +742,7 @@ describe('Note', () => { }, alice); assert.strictEqual(note2.status, 400); - assert.strictEqual(note2.body.error.code, 'CONTAINS_PROHIBITED_WORDS'); + assert.strictEqual(castAsError(note2.body).error.code, 'CONTAINS_PROHIBITED_WORDS'); }); test('禁止ワードを含む投稿はエラーになる (スペースアンド)', async () => { @@ -744,7 +759,7 @@ describe('Note', () => { }, alice); assert.strictEqual(note2.status, 400); - assert.strictEqual(note2.body.error.code, 'CONTAINS_PROHIBITED_WORDS'); + assert.strictEqual(castAsError(note2.body).error.code, 'CONTAINS_PROHIBITED_WORDS'); }); test('禁止ワードを含んでるリモートノートもエラーになる', async () => { @@ -786,7 +801,7 @@ describe('Note', () => { priority: 1, value: 0, }, - } as any, + }, }, root); assert.strictEqual(res.status, 200); @@ -807,7 +822,7 @@ describe('Note', () => { }, alice); assert.strictEqual(note.status, 400); - assert.strictEqual(note.body.error.code, 'CONTAINS_TOO_MANY_MENTIONS'); + assert.strictEqual(castAsError(note.body).error.code, 'CONTAINS_TOO_MANY_MENTIONS'); await api('admin/roles/unassign', { userId: alice.id, @@ -840,7 +855,7 @@ describe('Note', () => { priority: 1, value: 0, }, - } as any, + }, }, root); assert.strictEqual(res.status, 200); @@ -863,7 +878,7 @@ describe('Note', () => { }, alice); assert.strictEqual(note.status, 400); - assert.strictEqual(note.body.error.code, 'CONTAINS_TOO_MANY_MENTIONS'); + assert.strictEqual(castAsError(note.body).error.code, 'CONTAINS_TOO_MANY_MENTIONS'); await api('admin/roles/unassign', { userId: alice.id, @@ -896,7 +911,7 @@ describe('Note', () => { priority: 1, value: 1, }, - } as any, + }, }, root); assert.strictEqual(res.status, 200); @@ -951,6 +966,7 @@ describe('Note', () => { assert.strictEqual(deleteOneRes.status, 204); let mainNote = await Notes.findOneBy({ id: mainNoteRes.body.createdNote.id }); + assert.ok(mainNote); assert.strictEqual(mainNote.repliesCount, 1); const deleteTwoRes = await api('notes/delete', { @@ -959,6 +975,7 @@ describe('Note', () => { assert.strictEqual(deleteTwoRes.status, 204); mainNote = await Notes.findOneBy({ id: mainNoteRes.body.createdNote.id }); + assert.ok(mainNote); assert.strictEqual(mainNote.repliesCount, 0); }); }); @@ -980,7 +997,7 @@ describe('Note', () => { }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'UNAVAILABLE'); + assert.strictEqual(castAsError(res.body).error.code, 'UNAVAILABLE'); }); afterAll(async () => { @@ -992,7 +1009,7 @@ describe('Note', () => { const res = await api('notes/translate', { noteId: 'foo', targetLang: 'ja' }, alice); assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'NO_SUCH_NOTE'); + assert.strictEqual(castAsError(res.body).error.code, 'NO_SUCH_NOTE'); }); test('不可視なノートは翻訳できない', async () => { @@ -1000,7 +1017,7 @@ describe('Note', () => { const bobTranslateAttempt = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, bob); assert.strictEqual(bobTranslateAttempt.status, 400); - assert.strictEqual(bobTranslateAttempt.body.error.code, 'CANNOT_TRANSLATE_INVISIBLE_NOTE'); + assert.strictEqual(castAsError(bobTranslateAttempt.body).error.code, 'CANNOT_TRANSLATE_INVISIBLE_NOTE'); }); test('text: null なノートを翻訳すると空のレスポンスが返ってくる', async () => { @@ -1016,7 +1033,7 @@ describe('Note', () => { // NOTE: デフォルトでは登録されていないので落ちる assert.strictEqual(res.status, 400); - assert.strictEqual(res.body.error.code, 'UNAVAILABLE'); + assert.strictEqual(castAsError(res.body).error.code, 'UNAVAILABLE'); }); }); }); diff --git a/packages/backend/test/e2e/renote-mute.ts b/packages/backend/test/e2e/renote-mute.ts index 1abbb4f044..0f636b9ae2 100644 --- a/packages/backend/test/e2e/renote-mute.ts +++ b/packages/backend/test/e2e/renote-mute.ts @@ -6,7 +6,8 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; -import { api, post, signup, sleep, waitFire } from '../utils.js'; +import { setTimeout } from 'node:timers/promises'; +import { api, post, signup, waitFire } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Renote Mute', () => { @@ -35,15 +36,15 @@ describe('Renote Mute', () => { const carolNote = await post(carol, { text: 'hi' }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolRenote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolRenote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); }); test('タイムラインにリノートミュートしているユーザーの引用が含まれる', async () => { @@ -52,15 +53,15 @@ describe('Renote Mute', () => { const carolNote = await post(carol, { text: 'hi' }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolRenote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolRenote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); }); // #12956 @@ -69,14 +70,14 @@ describe('Renote Mute', () => { const bobRenote = await post(bob, { renoteId: carolNote.id }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobRenote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobRenote.id), true); }); test('ストリームにリノートミュートしているユーザーのリノートが流れない', async () => { diff --git a/packages/backend/test/e2e/streaming.ts b/packages/backend/test/e2e/streaming.ts index b0a70074c6..72f26a38e0 100644 --- a/packages/backend/test/e2e/streaming.ts +++ b/packages/backend/test/e2e/streaming.ts @@ -34,6 +34,7 @@ describe('Streaming', () => { let kyoko: misskey.entities.SignupResponse; let chitose: misskey.entities.SignupResponse; let kanako: misskey.entities.SignupResponse; + let erin: misskey.entities.SignupResponse; // Remote users let akari: misskey.entities.SignupResponse; @@ -53,6 +54,7 @@ describe('Streaming', () => { kyoko = await signup({ username: 'kyoko' }); chitose = await signup({ username: 'chitose' }); kanako = await signup({ username: 'kanako' }); + erin = await signup({ username: 'erin' }); // erin: A generic fifth participant akari = await signup({ username: 'akari', host: 'example.com' }); chinatsu = await signup({ username: 'chinatsu', host: 'example.com' }); @@ -71,6 +73,12 @@ describe('Streaming', () => { // Follow: kyoko => chitose await api('following/create', { userId: chitose.id }, kyoko); + // Follow: erin <=> ayano each other. + // erin => ayano: withReplies: true + await api('following/create', { userId: ayano.id, withReplies: true }, erin); + // ayano => erin: withReplies: false + await api('following/create', { userId: erin.id, withReplies: false }, ayano); + // Mute: chitose => kanako await api('mute/create', { userId: kanako.id }, chitose); @@ -297,6 +305,28 @@ describe('Streaming', () => { assert.strictEqual(fired, true); }); + + test('withReplies: true のとき自分のfollowers投稿に対するリプライが流れる', async () => { + const erinNote = await post(erin, { text: 'hi', visibility: 'followers' }); + const fired = await waitFire( + erin, 'homeTimeline', // erin:home + () => api('notes/create', { text: 'hello', replyId: erinNote.id }, ayano), // ayano reply to erin's followers post + msg => msg.type === 'note' && msg.body.userId === ayano.id, // wait ayano + ); + + assert.strictEqual(fired, true); + }); + + test('withReplies: false でも自分の投稿に対するリプライが流れる', async () => { + const ayanoNote = await post(ayano, { text: 'hi', visibility: 'followers' }); + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'hello', replyId: ayanoNote.id }, erin), // erin reply to ayano's followers post + msg => msg.type === 'note' && msg.body.userId === erin.id, // wait erin + ); + + assert.strictEqual(fired, true); + }); }); // Home describe('Local Timeline', () => { @@ -475,6 +505,38 @@ describe('Streaming', () => { assert.strictEqual(fired, false); }); + + test('withReplies: true のとき自分のfollowers投稿に対するリプライが流れる', async () => { + const erinNote = await post(erin, { text: 'hi', visibility: 'followers' }); + const fired = await waitFire( + erin, 'homeTimeline', // erin:home + () => api('notes/create', { text: 'hello', replyId: erinNote.id }, ayano), // ayano reply to erin's followers post + msg => msg.type === 'note' && msg.body.userId === ayano.id, // wait ayano + ); + + assert.strictEqual(fired, true); + }); + + test('withReplies: false でも自分の投稿に対するリプライが流れる', async () => { + const ayanoNote = await post(ayano, { text: 'hi', visibility: 'followers' }); + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'hello', replyId: ayanoNote.id }, erin), // erin reply to ayano's followers post + msg => msg.type === 'note' && msg.body.userId === erin.id, // wait erin + ); + + assert.strictEqual(fired, true); + }); + + test('withReplies: true のフォローしていない人のfollowersノートに対するリプライが流れない', async () => { + const fired = await waitFire( + erin, 'homeTimeline', // erin:home + () => api('notes/create', { text: 'hello', replyId: chitose.id }, ayano), // ayano reply to chitose's post + msg => msg.type === 'note' && msg.body.userId === ayano.id, // wait ayano + ); + + assert.strictEqual(fired, false); + }); }); describe('Global Timeline', () => { diff --git a/packages/backend/test/e2e/synalio/abuse-report.ts b/packages/backend/test/e2e/synalio/abuse-report.ts index b0cc3d13ec..c98d199f35 100644 --- a/packages/backend/test/e2e/synalio/abuse-report.ts +++ b/packages/backend/test/e2e/synalio/abuse-report.ts @@ -5,65 +5,24 @@ import { entities } from 'misskey-js'; import { beforeEach, describe, test } from '@jest/globals'; -import Fastify from 'fastify'; -import { api, randomString, role, signup, startJobQueue, UserToken } from '../../utils.js'; +import { + api, + captureWebhook, + randomString, + role, + signup, + startJobQueue, + UserToken, + WEBHOOK_HOST, +} from '../../utils.js'; import type { INestApplicationContext } from '@nestjs/common'; -const WEBHOOK_HOST = 'http://localhost:15080'; -const WEBHOOK_PORT = 15080; -process.env.NODE_ENV = 'test'; - describe('[シナリオ] ユーザ通報', () => { let queue: INestApplicationContext; let admin: entities.SignupResponse; let alice: entities.SignupResponse; let bob: entities.SignupResponse; - type SystemWebhookPayload = { - server: string; - hookId: string; - eventId: string; - createdAt: string; - type: string; - body: any; - } - - // ------------------------------------------------------------------------------------------- - - async function captureWebhook(postAction: () => Promise): Promise { - const fastify = Fastify(); - - let timeoutHandle: NodeJS.Timeout | null = null; - const result = await new Promise(async (resolve, reject) => { - fastify.all('/', async (req, res) => { - timeoutHandle && clearTimeout(timeoutHandle); - - const body = JSON.stringify(req.body); - res.status(200).send('ok'); - await fastify.close(); - resolve(body); - }); - - await fastify.listen({ port: WEBHOOK_PORT }); - - timeoutHandle = setTimeout(async () => { - await fastify.close(); - reject(new Error('timeout')); - }, 3000); - - try { - await postAction(); - } catch (e) { - await fastify.close(); - reject(e); - } - }); - - await fastify.close(); - - return JSON.parse(result) as T; - } - async function createSystemWebhook(args?: Partial, credential?: UserToken): Promise { const res = await api( 'admin/system-webhook/create', @@ -198,7 +157,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: webhookBody1.body.id, - forward: false, }, admin); }); @@ -255,7 +213,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: abuseReportId, - forward: false, }, admin); }); @@ -298,7 +255,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: webhookBody1.body.id, - forward: false, }, admin); }).catch(e => e.message); @@ -329,7 +285,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: abuseReportId, - forward: false, }, admin); }).catch(e => e.message); @@ -360,7 +315,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: abuseReportId, - forward: false, }, admin); }).catch(e => e.message); @@ -391,7 +345,6 @@ describe('[シナリオ] ユーザ通報', () => { const webhookBody2 = await captureWebhook(async () => { await resolveAbuseReport({ reportId: abuseReportId, - forward: false, }, admin); }).catch(e => e.message); diff --git a/packages/backend/test/e2e/synalio/user-create.ts b/packages/backend/test/e2e/synalio/user-create.ts new file mode 100644 index 0000000000..cb0f68dfea --- /dev/null +++ b/packages/backend/test/e2e/synalio/user-create.ts @@ -0,0 +1,130 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { setTimeout } from 'node:timers/promises'; +import { entities } from 'misskey-js'; +import { beforeEach, describe, test } from '@jest/globals'; +import { + api, + captureWebhook, + randomString, + role, + signup, + startJobQueue, + UserToken, + WEBHOOK_HOST, +} from '../../utils.js'; +import type { INestApplicationContext } from '@nestjs/common'; + +describe('[シナリオ] ユーザ作成', () => { + let queue: INestApplicationContext; + let admin: entities.SignupResponse; + + async function createSystemWebhook(args?: Partial, credential?: UserToken): Promise { + const res = await api( + 'admin/system-webhook/create', + { + isActive: true, + name: randomString(), + on: ['userCreated'], + url: WEBHOOK_HOST, + secret: randomString(), + ...args, + }, + credential ?? admin, + ); + return res.body; + } + + // ------------------------------------------------------------------------------------------- + + beforeAll(async () => { + queue = await startJobQueue(); + admin = await signup({ username: 'admin' }); + + await role(admin, { isAdministrator: true }); + }, 1000 * 60 * 2); + + afterAll(async () => { + await queue.close(); + }); + + // ------------------------------------------------------------------------------------------- + + describe('SystemWebhook', () => { + beforeEach(async () => { + const webhooks = await api('admin/system-webhook/list', {}, admin); + for (const webhook of webhooks.body) { + await api('admin/system-webhook/delete', { id: webhook.id }, admin); + } + }); + + test('ユーザが作成された -> userCreatedが送出される', async () => { + const webhook = await createSystemWebhook({ + on: ['userCreated'], + isActive: true, + }); + + let alice: any = null; + const webhookBody = await captureWebhook(async () => { + alice = await signup({ username: 'alice' }); + }); + + // webhookの送出後にいろいろやってるのでちょっと待つ必要がある + await setTimeout(2000); + + console.log(alice); + console.log(JSON.stringify(webhookBody, null, 2)); + + expect(webhookBody.hookId).toBe(webhook.id); + expect(webhookBody.type).toBe('userCreated'); + + const body = webhookBody.body as entities.UserLite; + expect(alice.id).toBe(body.id); + expect(alice.name).toBe(body.name); + expect(alice.username).toBe(body.username); + expect(alice.host).toBe(body.host); + expect(alice.avatarUrl).toBe(body.avatarUrl); + expect(alice.avatarBlurhash).toBe(body.avatarBlurhash); + expect(alice.avatarDecorations).toEqual(body.avatarDecorations); + expect(alice.isBot).toBe(body.isBot); + expect(alice.isCat).toBe(body.isCat); + expect(alice.instance).toEqual(body.instance); + expect(alice.emojis).toEqual(body.emojis); + expect(alice.onlineStatus).toBe(body.onlineStatus); + expect(alice.badgeRoles).toEqual(body.badgeRoles); + }); + + test('ユーザ作成 -> userCreatedが未許可の場合は送出されない', async () => { + await createSystemWebhook({ + on: [], + isActive: true, + }); + + let alice: any = null; + const webhookBody = await captureWebhook(async () => { + alice = await signup({ username: 'alice' }); + }).catch(e => e.message); + + expect(webhookBody).toBe('timeout'); + expect(alice.id).not.toBeNull(); + }); + + test('ユーザ作成 -> Webhookが無効の場合は送出されない', async () => { + await createSystemWebhook({ + on: ['userCreated'], + isActive: false, + }); + + let alice: any = null; + const webhookBody = await captureWebhook(async () => { + alice = await signup({ username: 'alice' }); + }).catch(e => e.message); + + expect(webhookBody).toBe('timeout'); + expect(alice.id).not.toBeNull(); + }); + }); +}); diff --git a/packages/backend/test/e2e/thread-mute.ts b/packages/backend/test/e2e/thread-mute.ts index 53bb6eb765..1ac99df884 100644 --- a/packages/backend/test/e2e/thread-mute.ts +++ b/packages/backend/test/e2e/thread-mute.ts @@ -33,9 +33,9 @@ describe('Note thread mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolReply.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolReplyWithoutMention.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolReply.id), false); + assert.strictEqual(res.body.some(note => note.id === carolReplyWithoutMention.id), false); }); test('ミュートしているスレッドからメンションされても、hasUnreadMentions が true にならない', async () => { @@ -93,8 +93,8 @@ describe('Note thread mute', () => { assert.strictEqual(res.status, 200); assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.some((notification: any) => notification.note.id === carolReply.id), false); - assert.strictEqual(res.body.some((notification: any) => notification.note.id === carolReplyWithoutMention.id), false); + assert.strictEqual(res.body.some(notification => 'note' in notification && notification.note.id === carolReply.id), false); + assert.strictEqual(res.body.some(notification => 'note' in notification && notification.note.id === carolReplyWithoutMention.id), false); // NOTE: bobの投稿はスレッドミュート前に行われたため通知に含まれていてもよい }); diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index f6cc2bac28..d12be2a9ac 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -7,16 +7,17 @@ // pnpm jest -- e2e/timelines.ts import * as assert from 'assert'; +import { setTimeout } from 'node:timers/promises'; import { Redis } from 'ioredis'; +import { api, post, randomString, sendEnvUpdateRequest, signup, uploadUrl } from '../utils.js'; import { loadConfig } from '@/config.js'; -import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js'; function genHost() { return randomString() + '.example.com'; } function waitForPushToTl() { - return sleep(500); + return setTimeout(500); } let redisForTimelines: Redis; @@ -36,15 +37,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === aliceNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.find(note => note.id === aliceNote.id)?.text, 'hi'); }); test.concurrent('フォローしているユーザーのノートが含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi' }); const carolNote = await post(carol, { text: 'hi' }); @@ -52,15 +53,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('フォローしているユーザーの visibility: followers なノートが含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); const carolNote = await post(carol, { text: 'hi' }); @@ -68,16 +69,16 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'hi'); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id)?.text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: false でフォローしているユーザーの他人への返信が含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -85,8 +86,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーの他人への返信が含まれる', async () => { @@ -94,7 +95,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -102,8 +103,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーの他人へのDM返信が含まれない', async () => { @@ -111,7 +112,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); @@ -119,16 +120,17 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーの他人の visibility: followers な投稿への返信が含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); + await api('following/create', { userId: carol.id }, bob); await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -136,8 +138,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーの行った別のフォローしているユーザーの visibility: followers な投稿への返信が含まれる', async () => { @@ -147,7 +149,7 @@ describe('Timelines', () => { await api('following/create', { userId: carol.id }, alice); await api('following/create', { userId: carol.id }, bob); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -155,9 +157,27 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); + assert.strictEqual(res.body.find(note => note.id === carolNote.id)?.text, 'hi'); + }); + + test.concurrent('withReplies: true でフォローしているユーザーの自分の visibility: followers な投稿への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await api('following/create', { userId: bob.id }, alice); + await api('following/create', { userId: alice.id }, bob); + await api('following/update', { userId: bob.id, withReplies: true }, alice); + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/timeline', { limit: 100 }, alice); + assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === carolNote.id).text, 'hi'); + assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); }); test.concurrent('withReplies: true でフォローしているユーザーの行った別のフォローしているユーザーの投稿への visibility: specified な返信が含まれない', async () => { @@ -166,7 +186,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/create', { userId: carol.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); @@ -174,15 +194,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); }); test.concurrent('withReplies: false でフォローしているユーザーのそのユーザー自身への返信が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); @@ -190,15 +210,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }); test.concurrent('withReplies: false でフォローしているユーザーからの自分への返信が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -206,8 +226,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('自分の他人への返信が含まれる', async () => { @@ -220,15 +240,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); }); test.concurrent('フォローしているユーザーの他人の投稿のリノートが含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); @@ -236,15 +256,15 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('[withRenotes: false] フォローしているユーザーの他人の投稿のリノートが含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); @@ -254,15 +274,15 @@ describe('Timelines', () => { withRenotes: false, }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('[withRenotes: false] フォローしているユーザーの他人の投稿の引用が含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -272,22 +292,22 @@ describe('Timelines', () => { withRenotes: false, }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('フォローしているユーザーの他人への visibility: specified なノートが含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしているユーザーが行ったミュートしているユーザーのリノートが含まれない', async () => { @@ -295,7 +315,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -303,8 +323,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーが行ったミュートしているユーザーの投稿への返信が含まれない', async () => { @@ -313,7 +333,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -321,8 +341,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => { @@ -337,7 +357,7 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => { @@ -352,14 +372,14 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withFiles: true] フォローしているユーザーのファイル付きノートのみ含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const [bobFile, carolFile] = await Promise.all([ uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'), uploadUrl(carol, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'), @@ -373,10 +393,10 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100, withFiles: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote2.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote2.id), false); }, 1000 * 10); test.concurrent('フォローしているユーザーのチャンネル投稿が含まれない', async () => { @@ -384,14 +404,14 @@ describe('Timelines', () => { const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', channelId: channel.id }); await waitForPushToTl(); const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('自分の visibility: specified なノートが含まれる', async () => { @@ -403,23 +423,23 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === aliceNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.find(note => note.id === aliceNote.id)?.text, 'hi'); }); test.concurrent('フォローしているユーザーの自身を visibleUserIds に指定した visibility: specified なノートが含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] }); await waitForPushToTl(); const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id)?.text, 'hi'); }); test.concurrent('フォローしていないユーザーの自身を visibleUserIds に指定した visibility: specified なノートが含まれない', async () => { @@ -431,21 +451,21 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしているユーザーの自身を visibleUserIds に指定していない visibility: specified なノートが含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしていないユーザーからの visibility: specified なノートに返信したときの自身のノートが含まれる', async () => { @@ -458,8 +478,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === aliceNote.id).text, 'ok'); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.find(note => note.id === aliceNote.id)?.text, 'ok'); }); /* TODO @@ -473,8 +493,8 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'ok'); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id).text, 'ok'); }); */ @@ -489,7 +509,45 @@ describe('Timelines', () => { const res = await api('notes/timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + }); + + test.concurrent('FTT: ローカルユーザーの HTL にはプッシュされる', async () => { + const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); + + await api('following/create', { + userId: alice.id, + }, bob); + + const aliceNote = await post(alice, { text: 'I\'m Alice.' }); + const bobNote = await post(bob, { text: 'I\'m Bob.' }); + const carolNote = await post(carol, { text: 'I\'m Carol.' }); + + await waitForPushToTl(); + + // NOTE: notes/timeline だと DB へのフォールバックが効くので Redis を直接見て確かめる + assert.strictEqual(await redisForTimelines.exists(`list:homeTimeline:${bob.id}`), 1); + + const bobHTL = await redisForTimelines.lrange(`list:homeTimeline:${bob.id}`, 0, -1); + assert.strictEqual(bobHTL.includes(aliceNote.id), true); + assert.strictEqual(bobHTL.includes(bobNote.id), true); + assert.strictEqual(bobHTL.includes(carolNote.id), false); + }); + + test.concurrent('FTT: リモートユーザーの HTL にはプッシュされない', async () => { + const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); + + await api('following/create', { + userId: alice.id, + }, bob); + + await post(alice, { text: 'I\'m Alice.' }); + await post(bob, { text: 'I\'m Bob.' }); + + await waitForPushToTl(); + + // NOTE: notes/timeline だと DB へのフォールバックが効くので Redis を直接見て確かめる + assert.strictEqual(await redisForTimelines.exists(`list:homeTimeline:${bob.id}`), 0); }); }); @@ -504,8 +562,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('他人の他人への返信が含まれない', async () => { @@ -518,8 +576,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); }); test.concurrent('他人のその人自身への返信が含まれる', async () => { @@ -532,8 +590,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }); test.concurrent('チャンネル投稿が含まれない', async () => { @@ -546,7 +604,7 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('リモートユーザーのノートが含まれない', async () => { @@ -558,7 +616,7 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); // 含まれても良いと思うけど実装が面倒なので含まれない @@ -566,7 +624,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi' }); @@ -574,15 +632,15 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('ミュートしているユーザーのノートが含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi' }); @@ -590,8 +648,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('フォローしているユーザーが行ったミュートしているユーザーのリノートが含まれない', async () => { @@ -599,7 +657,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -607,8 +665,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: true でフォローしているユーザーが行ったミュートしているユーザーの投稿への返信が含まれない', async () => { @@ -617,7 +675,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -625,15 +683,15 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), false); }); test.concurrent('withReplies: false でフォローしているユーザーからの自分への返信が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -641,8 +699,23 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + }); + + test.concurrent('withReplies: false でフォローしていないユーザーからの自分への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/local-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withReplies: true] 他人の他人への返信が含まれる', async () => { @@ -655,7 +728,7 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => { @@ -669,8 +742,8 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100, withFiles: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }, 1000 * 10); }); @@ -684,7 +757,7 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('ローカルユーザーの visibility: home なノートが含まれない', async () => { @@ -696,28 +769,28 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしているローカルユーザーの visibility: home なノートが含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('withReplies: false でフォローしているユーザーからの自分への返信が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -725,8 +798,64 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + }); + + test.concurrent('withReplies: true でフォローしているユーザーの他人の visibility: followers な投稿への返信が含まれない', async () => { + const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); + + await api('following/create', { userId: carol.id }, bob); + await api('following/create', { userId: bob.id }, alice); + await api('following/update', { userId: bob.id, withReplies: true }, alice); + await setTimeout(1000); + const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); + const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), false); + }); + + test.concurrent('withReplies: true でフォローしているユーザーの行った別のフォローしているユーザーの visibility: followers な投稿への返信が含まれる', async () => { + const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); + + await api('following/create', { userId: bob.id }, alice); + await api('following/create', { userId: carol.id }, alice); + await api('following/create', { userId: carol.id }, bob); + await api('following/update', { userId: bob.id, withReplies: true }, alice); + await setTimeout(1000); + const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); + const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); + assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.find((note: any) => note.id === carolNote.id)?.text, 'hi'); + }); + + test.concurrent('withReplies: true でフォローしているユーザーの自分の visibility: followers な投稿への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await api('following/create', { userId: bob.id }, alice); + await api('following/create', { userId: alice.id }, bob); + await api('following/update', { userId: bob.id, withReplies: true }, alice); + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); }); test.concurrent('他人の他人への返信が含まれない', async () => { @@ -739,8 +868,8 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === carolNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === carolNote.id), true); }); test.concurrent('リモートユーザーのノートが含まれない', async () => { @@ -752,7 +881,7 @@ describe('Timelines', () => { const res = await api('notes/local-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => { @@ -767,7 +896,7 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => { @@ -782,7 +911,22 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100 }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + }); + + test.concurrent('withReplies: false でフォローしていないユーザーからの自分への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/local-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withReplies: true] 他人の他人への返信が含まれる', async () => { @@ -795,7 +939,7 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => { @@ -809,8 +953,8 @@ describe('Timelines', () => { const res = await api('notes/hybrid-timeline', { limit: 100, withFiles: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }, 1000 * 10); }); @@ -820,14 +964,14 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('リスインしているフォローしていないユーザーの visibility: home なノートが含まれる', async () => { @@ -835,14 +979,14 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('リスインしているフォローしていないユーザーの visibility: followers なノートが含まれない', async () => { @@ -850,14 +994,14 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('リスインしているフォローしていないユーザーの他人への返信が含まれない', async () => { @@ -865,7 +1009,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -873,7 +1017,7 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('リスインしているフォローしていないユーザーのユーザー自身への返信が含まれる', async () => { @@ -881,7 +1025,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); @@ -889,8 +1033,8 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }); test.concurrent('withReplies: false でリスインしているフォローしていないユーザーからの自分への返信が含まれる', async () => { @@ -899,7 +1043,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -907,7 +1051,7 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('withReplies: false でリスインしているフォローしていないユーザーの他人への返信が含まれない', async () => { @@ -916,7 +1060,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -924,7 +1068,7 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('withReplies: true でリスインしているフォローしていないユーザーの他人への返信が含まれる', async () => { @@ -933,7 +1077,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -941,7 +1085,7 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('リスインしているフォローしているユーザーの visibility: home なノートが含まれる', async () => { @@ -950,14 +1094,14 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('リスインしているフォローしているユーザーの visibility: followers なノートが含まれる', async () => { @@ -966,15 +1110,15 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id)?.text, 'hi'); }); test.concurrent('リスインしている自分の visibility: followers なノートが含まれる', async () => { @@ -982,15 +1126,15 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: alice.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === aliceNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.find(note => note.id === aliceNote.id)?.text, 'hi'); }); test.concurrent('リスインしているユーザーのチャンネルノートが含まれない', async () => { @@ -999,14 +1143,14 @@ describe('Timelines', () => { const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', channelId: channel.id }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('[withFiles: true] リスインしているユーザーのファイル付きノートのみ含まれる', async () => { @@ -1022,8 +1166,8 @@ describe('Timelines', () => { const res = await api('notes/user-list-timeline', { listId: list.id, withFiles: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }, 1000 * 10); test.concurrent('リスインしているユーザーの自身宛ての visibility: specified なノートが含まれる', async () => { @@ -1031,15 +1175,15 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id)?.text, 'hi'); }); test.concurrent('リスインしているユーザーの自身宛てではない visibility: specified なノートが含まれない', async () => { @@ -1048,14 +1192,14 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/push', { listId: list.id, userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); const res = await api('notes/user-list-timeline', { listId: list.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); }); @@ -1069,7 +1213,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('フォローしていないユーザーの visibility: followers なノートが含まれない', async () => { @@ -1081,22 +1225,22 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('フォローしているユーザーの visibility: followers なノートが含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === bobNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + assert.strictEqual(res.body.find(note => note.id === bobNote.id)?.text, 'hi'); }); test.concurrent('自身の visibility: followers なノートが含まれる', async () => { @@ -1108,8 +1252,8 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: alice.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); - assert.strictEqual(res.body.find((note: any) => note.id === aliceNote.id).text, 'hi'); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.find(note => note.id === aliceNote.id)?.text, 'hi'); }); test.concurrent('チャンネル投稿が含まれない', async () => { @@ -1122,7 +1266,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('[withReplies: false] 他人への返信が含まれない', async () => { @@ -1136,8 +1280,8 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), false); }); test.concurrent('[withReplies: true] 他人への返信が含まれる', async () => { @@ -1151,8 +1295,8 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }); test.concurrent('[withReplies: true] 他人への visibility: specified な返信が含まれない', async () => { @@ -1166,8 +1310,8 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), false); }); test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => { @@ -1181,8 +1325,8 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withFiles: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), false); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); }, 1000 * 10); test.concurrent('[withChannelNotes: true] チャンネル投稿が含まれる', async () => { @@ -1195,7 +1339,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withChannelNotes: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('[withChannelNotes: true] 他人が取得した場合センシティブチャンネル投稿が含まれない', async () => { @@ -1208,7 +1352,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withChannelNotes: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('[withChannelNotes: true] 自分が取得した場合センシティブチャンネル投稿が含まれる', async () => { @@ -1221,14 +1365,14 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withChannelNotes: true }, bob); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); test.concurrent('ミュートしているユーザーに関連する投稿が含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -1236,14 +1380,14 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); test.concurrent('ミュートしていても userId に指定したユーザーの投稿が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('mute/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); const bobNote3 = await post(bob, { text: 'hi', renoteId: bobNote1.id }); @@ -1252,9 +1396,9 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote3.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote3.id), true); }); test.concurrent('自身の visibility: specified なノートが含まれる', async () => { @@ -1266,7 +1410,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: alice.id, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); }); test.concurrent('visibleUserIds に指定されてない visibility: specified なノートが含まれない', async () => { @@ -1278,7 +1422,7 @@ describe('Timelines', () => { const res = await api('users/notes', { userId: bob.id, withReplies: true }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), false); }); /** @see https://github.com/misskey-dev/misskey/issues/14000 */ diff --git a/packages/backend/test/e2e/user-notes.ts b/packages/backend/test/e2e/user-notes.ts index 331e053935..cc07c5ae71 100644 --- a/packages/backend/test/e2e/user-notes.ts +++ b/packages/backend/test/e2e/user-notes.ts @@ -17,8 +17,8 @@ describe('users/notes', () => { beforeAll(async () => { alice = await signup({ username: 'alice' }); - const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); - const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.png'); + const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); + const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.png'); jpgNote = await post(alice, { fileIds: [jpg.id], }); diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 3458e06384..822ca14ae6 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -7,9 +7,9 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import { inspect } from 'node:util'; -import { DEFAULT_POLICIES } from '@/core/RoleService.js'; import { api, post, role, signup, successfulApiCall, uploadFile } from '../utils.js'; import type * as misskey from 'misskey-js'; +import { DEFAULT_POLICIES } from '@/core/RoleService.js'; describe('ユーザー', () => { // エンティティとしてのユーザーを主眼においたテストを記述する @@ -83,9 +83,6 @@ describe('ユーザー', () => { publicReactions: user.publicReactions, followingVisibility: user.followingVisibility, followersVisibility: user.followersVisibility, - twoFactorEnabled: user.twoFactorEnabled, - usePasswordLessLogin: user.usePasswordLessLogin, - securityKeys: user.securityKeys, roles: user.roles, memo: user.memo, }); @@ -105,6 +102,7 @@ describe('ユーザー', () => { isRenoteMuted: user.isRenoteMuted ?? false, notify: user.notify ?? 'none', withReplies: user.withReplies ?? false, + followedMessage: user.isFollowing ? (user.followedMessage ?? null) : undefined, }); }; @@ -114,6 +112,7 @@ describe('ユーザー', () => { ...userDetailedNotMe(user), avatarId: user.avatarId, bannerId: user.bannerId, + followedMessage: user.followedMessage, isModerator: user.isModerator, isAdmin: user.isAdmin, injectFeaturedNote: user.injectFeaturedNote, @@ -147,6 +146,9 @@ describe('ユーザー', () => { achievements: user.achievements, loggedInDays: user.loggedInDays, policies: user.policies, + twoFactorEnabled: user.twoFactorEnabled, + usePasswordLessLogin: user.usePasswordLessLogin, + securityKeys: user.securityKeys, ...(security ? { email: user.email, emailVerified: user.emailVerified, @@ -231,7 +233,7 @@ describe('ユーザー', () => { rolePublic = await role(root, { isPublic: true, name: 'Public Role' }); await api('admin/roles/assign', { userId: userRolePublic.id, roleId: rolePublic.id }, root); userRoleBadge = await signup({ username: 'userRoleBadge' }); - roleBadge = await role(root, { asBadge: true, name: 'Badge Role' }); + roleBadge = await role(root, { asBadge: true, name: 'Badge Role', isPublic: true }); await api('admin/roles/assign', { userId: userRoleBadge.id, roleId: roleBadge.id }, root); userSilenced = await signup({ username: 'userSilenced' }); await post(userSilenced, { text: 'test' }); @@ -341,15 +343,13 @@ describe('ユーザー', () => { assert.strictEqual(response.publicReactions, true); assert.strictEqual(response.followingVisibility, 'public'); assert.strictEqual(response.followersVisibility, 'public'); - assert.strictEqual(response.twoFactorEnabled, false); - assert.strictEqual(response.usePasswordLessLogin, false); - assert.strictEqual(response.securityKeys, false); assert.deepStrictEqual(response.roles, []); assert.strictEqual(response.memo, null); // MeDetailedOnly assert.strictEqual(response.avatarId, null); assert.strictEqual(response.bannerId, null); + assert.strictEqual(response.followedMessage, null); assert.strictEqual(response.isModerator, false); assert.strictEqual(response.isAdmin, false); assert.strictEqual(response.injectFeaturedNote, true); @@ -382,6 +382,9 @@ describe('ユーザー', () => { assert.deepStrictEqual(response.achievements, []); assert.deepStrictEqual(response.loggedInDays, 0); assert.deepStrictEqual(response.policies, DEFAULT_POLICIES); + assert.strictEqual(response.twoFactorEnabled, false); + assert.strictEqual(response.usePasswordLessLogin, false); + assert.strictEqual(response.securityKeys, false); assert.notStrictEqual(response.email, undefined); assert.strictEqual(response.emailVerified, false); assert.deepStrictEqual(response.securityKeysList, []); @@ -413,6 +416,8 @@ describe('ユーザー', () => { { parameters: () => ({ description: 'x'.repeat(1500) }) }, { parameters: () => ({ description: 'x' }) }, { parameters: () => ({ description: 'My description' }) }, + { parameters: () => ({ followedMessage: null }) }, + { parameters: () => ({ followedMessage: 'Thank you' }) }, { parameters: () => ({ location: null }) }, { parameters: () => ({ location: 'x'.repeat(50) }) }, { parameters: () => ({ location: 'x' }) }, @@ -613,6 +618,9 @@ describe('ユーザー', () => { { label: 'Moderatorになっている', user: () => userModerator, me: () => userModerator, selector: (user: misskey.entities.MeDetailed) => user.isModerator }, // @ts-expect-error UserDetailedNotMe doesn't include isModerator { label: '自分以外から見たときはModeratorか判定できない', user: () => userModerator, selector: (user: misskey.entities.UserDetailedNotMe) => user.isModerator, expected: () => undefined }, + { label: '自分から見た場合に二要素認証関連のプロパティがセットされている', user: () => alice, me: () => alice, selector: (user: misskey.entities.MeDetailed) => user.twoFactorEnabled, expected: () => false }, + { label: '自分以外から見た場合に二要素認証関連のプロパティがセットされていない', user: () => alice, me: () => bob, selector: (user: misskey.entities.UserDetailedNotMe) => user.twoFactorEnabled, expected: () => undefined }, + { label: 'モデレーターから見た場合に二要素認証関連のプロパティがセットされている', user: () => alice, me: () => userModerator, selector: (user: misskey.entities.UserDetailedNotMe) => user.twoFactorEnabled, expected: () => false }, { label: 'サイレンスになっている', user: () => userSilenced, selector: (user: misskey.entities.UserDetailed) => user.isSilenced }, // FIXME: 落ちる //{ label: 'サスペンドになっている', user: () => userSuspended, selector: (user: misskey.entities.UserDetailed) => user.isSuspended }, @@ -655,7 +663,16 @@ describe('ユーザー', () => { iconUrl: roleBadge.iconUrl, displayOrder: roleBadge.displayOrder, }]); - assert.deepStrictEqual(response.roles, []); // バッヂだからといってrolesが取れるとは限らない + assert.deepStrictEqual(response.roles, [{ + id: roleBadge.id, + name: roleBadge.name, + color: roleBadge.color, + iconUrl: roleBadge.iconUrl, + description: roleBadge.description, + isModerator: roleBadge.isModerator, + isAdministrator: roleBadge.isAdministrator, + displayOrder: roleBadge.displayOrder, + }]); }); test('をID指定のリスト形式で取得することができる(空)', async () => { const parameters = { userIds: [] }; diff --git a/packages/backend/test/eslint.config.js b/packages/backend/test/eslint.config.js new file mode 100644 index 0000000000..a0f43babad --- /dev/null +++ b/packages/backend/test/eslint.config.js @@ -0,0 +1,22 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + globals: { + ...globals.node, + ...globals.jest, + }, + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/backend/test/jest.setup.ts b/packages/backend/test/jest.setup.ts index 861bc6db66..7c6dd6a55f 100644 --- a/packages/backend/test/jest.setup.ts +++ b/packages/backend/test/jest.setup.ts @@ -6,8 +6,6 @@ import { initTestDb, sendEnvResetRequest } from './utils.js'; beforeAll(async () => { - await Promise.all([ - initTestDb(false), - sendEnvResetRequest(), - ]); + await initTestDb(false); + await sendEnvResetRequest(); }); diff --git a/packages/backend/test/misc/mock-resolver.ts b/packages/backend/test/misc/mock-resolver.ts index 3c7e796700..c8f3db8aac 100644 --- a/packages/backend/test/misc/mock-resolver.ts +++ b/packages/backend/test/misc/mock-resolver.ts @@ -17,6 +17,7 @@ import type { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import type { FollowRequestsRepository, + MiMeta, NoteReactionsRepository, NotesRepository, PollsRepository, @@ -35,6 +36,7 @@ export class MockResolver extends Resolver { constructor(loggerService: LoggerService) { super( {} as Config, + {} as MiMeta, {} as UsersRepository, {} as NotesRepository, {} as PollsRepository, @@ -42,7 +44,6 @@ export class MockResolver extends Resolver { {} as FollowRequestsRepository, {} as UtilityService, {} as InstanceActorService, - {} as MetaService, {} as ApRequestService, {} as HttpRequestService, {} as ApRendererService, diff --git a/packages/backend/test/resources/192.jpg b/packages/backend/test/resources/192.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76374628e0acf2e3b85152d55c11c9a763027810 GIT binary patch literal 5131 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 literal 0 HcmV?d00001 diff --git a/packages/backend/test/resources/192.png b/packages/backend/test/resources/192.png new file mode 100644 index 0000000000000000000000000000000000000000..15fd1e3731210ad53f3948c1551a5be1f5ab1396 GIT binary patch literal 26568 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

WU5-N=dey=F`@4DEshA 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 E0Hgq>F#rGn literal 0 HcmV?d00001 diff --git a/packages/backend/test/resources/Lenna.jpg b/packages/backend/test/resources/Lenna.jpg deleted file mode 100644 index 6b5b32281c1ffd5893d23392169cc368d72e0823..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25360 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 O>~nN4ZJfRS|4jhJY`72r diff --git a/packages/backend/test/resources/Lenna.png b/packages/backend/test/resources/Lenna.png deleted file mode 100644 index 59ef68aabd033341028ccd2b1f6c5871c02b9d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 473831 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

NKMno`K4L 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�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

Xn*pCyUKBCz@Y#ZMoE`>cP57} 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%0ADm`};Qj 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 { { provide: SystemWebhookService, useFactory: () => ({ enqueueSystemWebhook: jest.fn() }), }, + { + provide: UserEntityService, useFactory: () => ({ pack: (v: any) => v }), + }, { provide: EmailService, useFactory: () => ({ sendEmail: jest.fn() }), }, diff --git a/packages/backend/test/unit/ApMfmService.ts b/packages/backend/test/unit/ApMfmService.ts index 79cb81f5c9..e81a321c9b 100644 --- a/packages/backend/test/unit/ApMfmService.ts +++ b/packages/backend/test/unit/ApMfmService.ts @@ -23,10 +23,10 @@ describe('ApMfmService', () => { describe('getNoteHtml', () => { test('Do not provide _misskey_content for simple text', () => { - const note: MiNote = { + const note = { text: 'テキスト #タグ @mention 🍊 :emoji: https://example.com', mentionedRemoteUsers: '[]', - } as any; + }; const { content, noMisskeyContent } = apMfmService.getNoteHtml(note); @@ -35,10 +35,10 @@ describe('ApMfmService', () => { }); test('Provide _misskey_content for MFM', () => { - const note: MiNote = { + const note = { text: '$[tada foo]', mentionedRemoteUsers: '[]', - } as any; + }; const { content, noMisskeyContent } = apMfmService.getNoteHtml(note); diff --git a/packages/backend/test/unit/FileInfoService.ts b/packages/backend/test/unit/FileInfoService.ts index 40d187f5a8..29bd03a201 100644 --- a/packages/backend/test/unit/FileInfoService.ts +++ b/packages/backend/test/unit/FileInfoService.ts @@ -12,7 +12,7 @@ import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; import { afterAll, beforeAll, describe, test } from '@jest/globals'; import { GlobalModule } from '@/GlobalModule.js'; -import { FileInfoService } from '@/core/FileInfoService.js'; +import { FileInfo, FileInfoService } from '@/core/FileInfoService.js'; //import { DI } from '@/di-symbols.js'; import { AiService } from '@/core/AiService.js'; import { LoggerService } from '@/core/LoggerService.js'; @@ -28,6 +28,15 @@ const moduleMocker = new ModuleMocker(global); describe('FileInfoService', () => { let app: TestingModule; let fileInfoService: FileInfoService; + const strip = (fileInfo: FileInfo): Omit, 'warnings' | 'blurhash' | 'sensitive' | 'porn'> => { + const fi: Partial = fileInfo; + delete fi.warnings; + delete fi.sensitive; + delete fi.blurhash; + delete fi.porn; + + return fi; + } beforeAll(async () => { app = await Test.createTestingModule({ @@ -63,11 +72,7 @@ describe('FileInfoService', () => { test('Empty file', async () => { const path = `${resources}/emptyfile`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 0, md5: 'd41d8cd98f00b204e9800998ecf8427e', @@ -83,32 +88,24 @@ describe('FileInfoService', () => { describe('IMAGE', () => { test('Generic JPEG', async () => { - const path = `${resources}/Lenna.jpg`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const path = `${resources}/192.jpg`; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { - size: 25360, - md5: '091b3f259662aa31e2ffef4519951168', + size: 5131, + md5: '8c9ed0677dd2b8f9f7472c3af247e5e3', type: { mime: 'image/jpeg', ext: 'jpg', }, - width: 512, - height: 512, + width: 192, + height: 192, orientation: undefined, }); }); test('Generic APNG', async () => { const path = `${resources}/anime.png`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 1868, md5: '08189c607bea3b952704676bb3c979e0', @@ -124,11 +121,7 @@ describe('FileInfoService', () => { test('Generic AGIF', async () => { const path = `${resources}/anime.gif`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 2248, md5: '32c47a11555675d9267aee1a86571e7e', @@ -144,11 +137,7 @@ describe('FileInfoService', () => { test('PNG with alpha', async () => { const path = `${resources}/with-alpha.png`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 3772, md5: 'f73535c3e1e27508885b69b10cf6e991', @@ -164,11 +153,7 @@ describe('FileInfoService', () => { test('Generic SVG', async () => { const path = `${resources}/image.svg`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 505, md5: 'b6f52b4b021e7b92cdd04509c7267965', @@ -185,11 +170,7 @@ describe('FileInfoService', () => { test('SVG with XML definition', async () => { // https://github.com/misskey-dev/misskey/issues/4413 const path = `${resources}/with-xml-def.svg`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 544, md5: '4b7a346cde9ccbeb267e812567e33397', @@ -205,11 +186,7 @@ describe('FileInfoService', () => { test('Dimension limit', async () => { const path = `${resources}/25000x25000.png`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 75933, md5: '268c5dde99e17cf8fe09f1ab3f97df56', @@ -225,11 +202,7 @@ describe('FileInfoService', () => { test('Rotate JPEG', async () => { const path = `${resources}/rotate.jpg`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); assert.deepStrictEqual(info, { size: 12624, md5: '68d5b2d8d1d1acbbce99203e3ec3857e', @@ -247,11 +220,7 @@ describe('FileInfoService', () => { describe('AUDIO', () => { test('MP3', async () => { const path = `${resources}/kick_gaba7.mp3`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; @@ -267,11 +236,7 @@ describe('FileInfoService', () => { test('WAV', async () => { const path = `${resources}/kick_gaba7.wav`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; @@ -287,11 +252,7 @@ describe('FileInfoService', () => { test('AAC', async () => { const path = `${resources}/kick_gaba7.aac`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; @@ -307,11 +268,7 @@ describe('FileInfoService', () => { test('FLAC', async () => { const path = `${resources}/kick_gaba7.flac`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; @@ -327,11 +284,7 @@ describe('FileInfoService', () => { test('MPEG-4 AUDIO (M4A)', async () => { const path = `${resources}/kick_gaba7.m4a`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; @@ -347,11 +300,7 @@ describe('FileInfoService', () => { test('WEBM AUDIO', async () => { const path = `${resources}/kick_gaba7.webm`; - const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; - delete info.warnings; - delete info.blurhash; - delete info.sensitive; - delete info.porn; + const info = strip(await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true })); delete info.width; delete info.height; delete info.orientation; diff --git a/packages/backend/test/unit/FlashService.ts b/packages/backend/test/unit/FlashService.ts new file mode 100644 index 0000000000..12ffaf3421 --- /dev/null +++ b/packages/backend/test/unit/FlashService.ts @@ -0,0 +1,152 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Test, TestingModule } from '@nestjs/testing'; +import { FlashService } from '@/core/FlashService.js'; +import { IdService } from '@/core/IdService.js'; +import { FlashsRepository, MiFlash, MiUser, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { GlobalModule } from '@/GlobalModule.js'; + +describe('FlashService', () => { + let app: TestingModule; + let service: FlashService; + + // -------------------------------------------------------------------------------------- + + let flashsRepository: FlashsRepository; + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + let idService: IdService; + + // -------------------------------------------------------------------------------------- + + let root: MiUser; + let alice: MiUser; + let bob: MiUser; + + // -------------------------------------------------------------------------------------- + + async function createFlash(data: Partial) { + return flashsRepository.insert({ + id: idService.gen(), + updatedAt: new Date(), + userId: root.id, + title: 'title', + summary: 'summary', + script: 'script', + permissions: [], + likedCount: 0, + ...data, + }).then(x => flashsRepository.findOneByOrFail(x.identifiers[0])); + } + + async function createUser(data: Partial = {}) { + const user = await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.insert({ + userId: user.id, + }); + + return user; + } + + // -------------------------------------------------------------------------------------- + + beforeEach(async () => { + app = await Test.createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + FlashService, + IdService, + ], + }).compile(); + + service = app.get(FlashService); + + flashsRepository = app.get(DI.flashsRepository); + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + idService = app.get(IdService); + + root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true }); + alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false }); + bob = await createUser({ username: 'bob', usernameLower: 'bob', isRoot: false }); + }); + + afterEach(async () => { + await usersRepository.delete({}); + await userProfilesRepository.delete({}); + await flashsRepository.delete({}); + }); + + afterAll(async () => { + await app.close(); + }); + + // -------------------------------------------------------------------------------------- + + describe('featured', () => { + test('should return featured flashes', async () => { + const flash1 = await createFlash({ likedCount: 1 }); + const flash2 = await createFlash({ likedCount: 2 }); + const flash3 = await createFlash({ likedCount: 3 }); + + const result = await service.featured({ + offset: 0, + limit: 10, + }); + + expect(result).toEqual([flash3, flash2, flash1]); + }); + + test('should return featured flashes public visibility only', async () => { + const flash1 = await createFlash({ likedCount: 1, visibility: 'public' }); + const flash2 = await createFlash({ likedCount: 2, visibility: 'public' }); + const flash3 = await createFlash({ likedCount: 3, visibility: 'private' }); + + const result = await service.featured({ + offset: 0, + limit: 10, + }); + + expect(result).toEqual([flash2, flash1]); + }); + + test('should return featured flashes with offset', async () => { + const flash1 = await createFlash({ likedCount: 1 }); + const flash2 = await createFlash({ likedCount: 2 }); + const flash3 = await createFlash({ likedCount: 3 }); + + const result = await service.featured({ + offset: 1, + limit: 10, + }); + + expect(result).toEqual([flash2, flash1]); + }); + + test('should return featured flashes with limit', async () => { + const flash1 = await createFlash({ likedCount: 1 }); + const flash2 = await createFlash({ likedCount: 2 }); + const flash3 = await createFlash({ likedCount: 3 }); + + const result = await service.featured({ + offset: 0, + limit: 2, + }); + + expect(result).toEqual([flash3, flash2]); + }); + }); +}); diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index 69fa4162fb..9c1b1008d6 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -5,13 +5,17 @@ process.env.NODE_ENV = 'test'; +import { setTimeout } from 'node:timers/promises'; import { jest } from '@jest/globals'; import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; import * as lolex from '@sinonjs/fake-timers'; +import type { TestingModule } from '@nestjs/testing'; +import type { MockFunctionMetadata } from 'jest-mock'; import { GlobalModule } from '@/GlobalModule.js'; import { RoleService } from '@/core/RoleService.js'; import { + MiMeta, MiRole, MiRoleAssignment, MiUser, @@ -29,9 +33,6 @@ import { secureRndstr } from '@/misc/secure-rndstr.js'; import { NotificationService } from '@/core/NotificationService.js'; import { RoleCondFormulaValue } from '@/models/Role.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { sleep } from '../utils.js'; -import type { TestingModule } from '@nestjs/testing'; -import type { MockFunctionMetadata } from 'jest-mock'; const moduleMocker = new ModuleMocker(global); @@ -41,7 +42,7 @@ describe('RoleService', () => { let usersRepository: UsersRepository; let rolesRepository: RolesRepository; let roleAssignmentsRepository: RoleAssignmentsRepository; - let metaService: jest.Mocked; + let meta: jest.Mocked; let notificationService: jest.Mocked; let clock: lolex.InstalledClock; @@ -142,7 +143,7 @@ describe('RoleService', () => { rolesRepository = app.get(DI.rolesRepository); roleAssignmentsRepository = app.get(DI.roleAssignmentsRepository); - metaService = app.get(MetaService) as jest.Mocked; + meta = app.get(DI.meta) as jest.Mocked; notificationService = app.get(NotificationService) as jest.Mocked; await roleService.onModuleInit(); @@ -164,11 +165,9 @@ describe('RoleService', () => { describe('getUserPolicies', () => { test('instance default policies', async () => { const user = await createUser(); - metaService.fetch.mockResolvedValue({ - policies: { - canManageCustomEmojis: false, - }, - } as any); + meta.policies = { + canManageCustomEmojis: false, + }; const result = await roleService.getUserPolicies(user.id); @@ -177,11 +176,9 @@ describe('RoleService', () => { test('instance default policies 2', async () => { const user = await createUser(); - metaService.fetch.mockResolvedValue({ - policies: { - canManageCustomEmojis: true, - }, - } as any); + meta.policies = { + canManageCustomEmojis: true, + }; const result = await roleService.getUserPolicies(user.id); @@ -201,11 +198,9 @@ describe('RoleService', () => { }, }); await roleService.assign(user.id, role.id); - metaService.fetch.mockResolvedValue({ - policies: { - canManageCustomEmojis: false, - }, - } as any); + meta.policies = { + canManageCustomEmojis: false, + }; const result = await roleService.getUserPolicies(user.id); @@ -236,11 +231,9 @@ describe('RoleService', () => { }); await roleService.assign(user.id, role1.id); await roleService.assign(user.id, role2.id); - metaService.fetch.mockResolvedValue({ - policies: { - driveCapacityMb: 50, - }, - } as any); + meta.policies = { + driveCapacityMb: 50, + }; const result = await roleService.getUserPolicies(user.id); @@ -260,11 +253,9 @@ describe('RoleService', () => { }, }); await roleService.assign(user.id, role.id, new Date(Date.now() + (1000 * 60 * 60 * 24))); - metaService.fetch.mockResolvedValue({ - policies: { - canManageCustomEmojis: false, - }, - } as any); + meta.policies = { + canManageCustomEmojis: false, + }; const result = await roleService.getUserPolicies(user.id); expect(result.canManageCustomEmojis).toBe(true); @@ -278,7 +269,7 @@ describe('RoleService', () => { // ストリーミング経由で反映されるまでちょっと待つ clock.uninstall(); - await sleep(100); + await setTimeout(100); const resultAfter25hAgain = await roleService.getUserPolicies(user.id); expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true); @@ -286,9 +277,9 @@ describe('RoleService', () => { }); describe('getModeratorIds', () => { - test('includeAdmins = false, excludeExpire = false', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + test('includeAdmins = false, includeRoot = false, excludeExpire = false', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }), ]); const role1 = await createRole({ name: 'admin', isAdministrator: true }); @@ -304,13 +295,17 @@ describe('RoleService', () => { assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), ]); - const result = await roleService.getModeratorIds(false, false); + const result = await roleService.getModeratorIds({ + includeAdmins: false, + includeRoot: false, + excludeExpire: false, + }); expect(result).toEqual([modeUser1.id, modeUser2.id]); }); - test('includeAdmins = false, excludeExpire = true', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + test('includeAdmins = false, includeRoot = false, excludeExpire = true', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }), ]); const role1 = await createRole({ name: 'admin', isAdministrator: true }); @@ -326,13 +321,17 @@ describe('RoleService', () => { assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), ]); - const result = await roleService.getModeratorIds(false, true); + const result = await roleService.getModeratorIds({ + includeAdmins: false, + includeRoot: false, + excludeExpire: true, + }); expect(result).toEqual([modeUser1.id]); }); - test('includeAdmins = true, excludeExpire = false', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + test('includeAdmins = true, includeRoot = false, excludeExpire = false', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }), ]); const role1 = await createRole({ name: 'admin', isAdministrator: true }); @@ -348,13 +347,17 @@ describe('RoleService', () => { assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), ]); - const result = await roleService.getModeratorIds(true, false); + const result = await roleService.getModeratorIds({ + includeAdmins: true, + includeRoot: false, + excludeExpire: false, + }); expect(result).toEqual([adminUser1.id, adminUser2.id, modeUser1.id, modeUser2.id]); }); - test('includeAdmins = true, excludeExpire = true', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + test('includeAdmins = true, includeRoot = false, excludeExpire = true', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }), ]); const role1 = await createRole({ name: 'admin', isAdministrator: true }); @@ -370,9 +373,111 @@ describe('RoleService', () => { assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), ]); - const result = await roleService.getModeratorIds(true, true); + const result = await roleService.getModeratorIds({ + includeAdmins: true, + includeRoot: false, + excludeExpire: true, + }); expect(result).toEqual([adminUser1.id, modeUser1.id]); }); + + test('includeAdmins = false, includeRoot = true, excludeExpire = false', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createUser({ isRoot: true }), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), + ]); + + const result = await roleService.getModeratorIds({ + includeAdmins: false, + includeRoot: true, + excludeExpire: false, + }); + expect(result).toEqual([modeUser1.id, modeUser2.id, rootUser.id]); + }); + + test('root has moderator role', async () => { + const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser({ isRoot: true }), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: rootUser.id, roleId: role2.id }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + ]); + + const result = await roleService.getModeratorIds({ + includeAdmins: false, + includeRoot: true, + excludeExpire: false, + }); + expect(result).toEqual([modeUser1.id, rootUser.id]); + }); + + test('root has administrator role', async () => { + const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser({ isRoot: true }), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: rootUser.id, roleId: role1.id }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + ]); + + const result = await roleService.getModeratorIds({ + includeAdmins: true, + includeRoot: true, + excludeExpire: false, + }); + expect(result).toEqual([adminUser1.id, modeUser1.id, rootUser.id]); + }); + + test('root has moderator role(expire)', async () => { + const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([ + createUser(), createUser(), createUser(), createUser({ isRoot: true }), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: modeUser1.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: rootUser.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + ]); + + const result = await roleService.getModeratorIds({ + includeAdmins: false, + includeRoot: true, + excludeExpire: true, + }); + expect(result).toEqual([rootUser.id]); + }); }); describe('conditional role', () => { @@ -807,7 +912,7 @@ describe('RoleService', () => { await roleService.assign(user.id, role.id); clock.uninstall(); - await sleep(100); + await setTimeout(100); const assignments = await roleAssignmentsRepository.find({ where: { @@ -835,7 +940,7 @@ describe('RoleService', () => { await roleService.assign(user.id, role.id); clock.uninstall(); - await sleep(100); + await setTimeout(100); const assignments = await roleAssignmentsRepository.find({ where: { diff --git a/packages/backend/test/unit/SigninWithPasskeyApiService.ts b/packages/backend/test/unit/SigninWithPasskeyApiService.ts new file mode 100644 index 0000000000..bae2b88c60 --- /dev/null +++ b/packages/backend/test/unit/SigninWithPasskeyApiService.ts @@ -0,0 +1,182 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { IncomingHttpHeaders } from 'node:http'; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, jest, test } from '@jest/globals'; +import { Test, TestingModule } from '@nestjs/testing'; +import { FastifyReply, FastifyRequest } from 'fastify'; +import { AuthenticationResponseJSON } from '@simplewebauthn/types'; +import { HttpHeader } from 'fastify/types/utils.js'; +import { MockFunctionMetadata, ModuleMocker } from 'jest-mock'; +import { MiUser } from '@/models/User.js'; +import { MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { DI } from '@/di-symbols.js'; +import { CoreModule } from '@/core/CoreModule.js'; +import { SigninWithPasskeyApiService } from '@/server/api/SigninWithPasskeyApiService.js'; +import { RateLimiterService } from '@/server/api/RateLimiterService.js'; +import { WebAuthnService } from '@/core/WebAuthnService.js'; +import { SigninService } from '@/server/api/SigninService.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; + +const moduleMocker = new ModuleMocker(global); + +class FakeLimiter { + public async limit() { + return; + } +} + +class FakeSigninService { + public signin(..._args: any): any { + return true; + } +} + +class DummyFastifyReply { + public statusCode: number; + code(num: number): void { + this.statusCode = num; + } + header(_key: HttpHeader, _value: any): void { + } +} +class DummyFastifyRequest { + public ip: string; + public body: {credential: any, context: string}; + public headers: IncomingHttpHeaders = { 'accept': 'application/json' }; + constructor(body?: any) { + this.ip = '0.0.0.0'; + this.body = body; + } +} + +type ApiFastifyRequestType = FastifyRequest<{ + Body: { + credential?: AuthenticationResponseJSON; + context?: string; + }; +}>; + +describe('SigninWithPasskeyApiService', () => { + let app: TestingModule; + let passkeyApiService: SigninWithPasskeyApiService; + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + let webAuthnService: WebAuthnService; + let idService: IdService; + let FakeWebauthnVerify: ()=>Promise; + + async function createUser(data: Partial = {}) { + const user = await usersRepository + .save({ + ...data, + }); + return user; + } + + async function createUserProfile(data: Partial = {}) { + const userProfile = await userProfilesRepository + .save({ ...data }, + ); + return userProfile; + } + + beforeAll(async () => { + app = await Test.createTestingModule({ + imports: [GlobalModule, CoreModule], + providers: [ + SigninWithPasskeyApiService, + { provide: RateLimiterService, useClass: FakeLimiter }, + { provide: SigninService, useClass: FakeSigninService }, + ], + }).useMocker((token) => { + if (typeof token === 'function') { + const mockMetadata = moduleMocker.getMetadata(token) as MockFunctionMetadata; + const Mock = moduleMocker.generateFromMetadata(mockMetadata); + return new Mock(); + } + }).compile(); + passkeyApiService = app.get(SigninWithPasskeyApiService); + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + webAuthnService = app.get(WebAuthnService); + idService = app.get(IdService); + }); + + beforeEach(async () => { + const uid = idService.gen(); + FakeWebauthnVerify = async () => { + return uid; + }; + jest.spyOn(webAuthnService, 'verifySignInWithPasskeyAuthentication').mockImplementation(FakeWebauthnVerify); + + const dummyUser = { + id: uid, username: uid, usernameLower: uid.toLocaleLowerCase(), uri: null, host: null, + }; + const dummyProfile = { + userId: uid, + password: 'qwerty', + usePasswordLessLogin: true, + }; + await createUser(dummyUser); + await createUserProfile(dummyProfile); + }); + + afterAll(async () => { + await app.close(); + }); + + describe('Get Passkey Options', () => { + it('Should return passkey Auth Options', async () => { + const req = new DummyFastifyRequest({}) as ApiFastifyRequestType; + const res = new DummyFastifyReply() as unknown as FastifyReply; + const res_body = await passkeyApiService.signin(req, res); + expect(res.statusCode).toBe(200); + expect((res_body as any).option).toBeDefined(); + expect(typeof (res_body as any).context).toBe('string'); + }); + }); + describe('Try Passkey Auth', () => { + it('Should Success', async () => { + const req = new DummyFastifyRequest({ context: 'auth-context', credential: { dummy: [] } }) as ApiFastifyRequestType; + const res = new DummyFastifyReply() as FastifyReply; + const res_body = await passkeyApiService.signin(req, res); + expect((res_body as any).signinResponse).toBeDefined(); + }); + + it('Should return 400 Without Auth Context', async () => { + const req = new DummyFastifyRequest({ credential: { dummy: [] } }) as ApiFastifyRequestType; + const res = new DummyFastifyReply() as FastifyReply; + const res_body = await passkeyApiService.signin(req, res); + expect(res.statusCode).toBe(400); + expect((res_body as any).error?.id).toStrictEqual('1658cc2e-4495-461f-aee4-d403cdf073c1'); + }); + + it('Should return 403 When Challenge Verify fail', async () => { + const req = new DummyFastifyRequest({ context: 'misskey-1234', credential: { dummy: [] } }) as ApiFastifyRequestType; + const res = new DummyFastifyReply() as FastifyReply; + jest.spyOn(webAuthnService, 'verifySignInWithPasskeyAuthentication') + .mockImplementation(async () => { + throw new IdentifiableError('THIS_ERROR_CODE_SHOULD_BE_FORWARDED'); + }); + const res_body = await passkeyApiService.signin(req, res); + expect(res.statusCode).toBe(403); + expect((res_body as any).error?.id).toStrictEqual('THIS_ERROR_CODE_SHOULD_BE_FORWARDED'); + }); + + it('Should return 403 When The user not Enabled Passwordless login', async () => { + const req = new DummyFastifyRequest({ context: 'misskey-1234', credential: { dummy: [] } }) as ApiFastifyRequestType; + const res = new DummyFastifyReply() as FastifyReply; + const userId = await FakeWebauthnVerify(); + const data = { userId: userId, usePasswordLessLogin: false }; + await userProfilesRepository.update({ userId: userId }, data); + const res_body = await passkeyApiService.signin(req, res); + expect(res.statusCode).toBe(403); + expect((res_body as any).error?.id).toStrictEqual('2d84773e-f7b7-4d0b-8f72-bb69b584c912'); + }); + }); +}); diff --git a/packages/backend/test/unit/SystemWebhookService.ts b/packages/backend/test/unit/SystemWebhookService.ts index 41b7f977ca..5401dd74d8 100644 --- a/packages/backend/test/unit/SystemWebhookService.ts +++ b/packages/backend/test/unit/SystemWebhookService.ts @@ -1,10 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ +import { setTimeout } from 'node:timers/promises'; import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals'; import { Test, TestingModule } from '@nestjs/testing'; +import { randomString } from '../utils.js'; import { MiUser } from '@/models/User.js'; import { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js'; import { SystemWebhooksRepository, UsersRepository } from '@/models/_.js'; @@ -16,7 +19,6 @@ import { DI } from '@/di-symbols.js'; import { QueueService } from '@/core/QueueService.js'; import { LoggerService } from '@/core/LoggerService.js'; import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { randomString, sleep } from '../utils.js'; describe('SystemWebhookService', () => { let app: TestingModule; @@ -312,7 +314,7 @@ describe('SystemWebhookService', () => { isActive: true, on: ['abuseReport'], }); - await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); + await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' } as any); expect(queueService.systemWebhookDeliver).toHaveBeenCalled(); }); @@ -322,7 +324,7 @@ describe('SystemWebhookService', () => { isActive: false, on: ['abuseReport'], }); - await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); + await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' } as any); expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); }); @@ -336,8 +338,8 @@ describe('SystemWebhookService', () => { isActive: true, on: ['abuseReportResolved'], }); - await service.enqueueSystemWebhook(webhook1.id, 'abuseReport', { foo: 'bar' }); - await service.enqueueSystemWebhook(webhook2.id, 'abuseReport', { foo: 'bar' }); + await service.enqueueSystemWebhook(webhook1.id, 'abuseReport', { foo: 'bar' } as any); + await service.enqueueSystemWebhook(webhook2.id, 'abuseReport', { foo: 'bar' } as any); expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); }); @@ -358,7 +360,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook]); @@ -377,7 +379,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([]); @@ -407,7 +409,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook2]); @@ -434,7 +436,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); @@ -457,7 +459,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook2]); @@ -481,7 +483,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); @@ -504,7 +506,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); diff --git a/packages/backend/test/unit/UserSearchService.ts b/packages/backend/test/unit/UserSearchService.ts new file mode 100644 index 0000000000..7ea325d420 --- /dev/null +++ b/packages/backend/test/unit/UserSearchService.ts @@ -0,0 +1,265 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Test, TestingModule } from '@nestjs/testing'; +import { describe, jest, test } from '@jest/globals'; +import { In } from 'typeorm'; +import { UserSearchService } from '@/core/UserSearchService.js'; +import { FollowingsRepository, MiUser, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { DI } from '@/di-symbols.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; + +describe('UserSearchService', () => { + let app: TestingModule; + let service: UserSearchService; + + let usersRepository: UsersRepository; + let followingsRepository: FollowingsRepository; + let idService: IdService; + let userProfilesRepository: UserProfilesRepository; + + let root: MiUser; + let alice: MiUser; + let alyce: MiUser; + let alycia: MiUser; + let alysha: MiUser; + let alyson: MiUser; + let alyssa: MiUser; + let bob: MiUser; + let bobbi: MiUser; + let bobbie: MiUser; + let bobby: MiUser; + + async function createUser(data: Partial = {}) { + const user = await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.insert({ + userId: user.id, + }); + + return user; + } + + async function createFollowings(follower: MiUser, followees: MiUser[]) { + for (const followee of followees) { + await followingsRepository.insert({ + id: idService.gen(), + followerId: follower.id, + followeeId: followee.id, + }); + } + } + + async function setActive(users: MiUser[]) { + for (const user of users) { + await usersRepository.update(user.id, { + updatedAt: new Date(), + }); + } + } + + async function setInactive(users: MiUser[]) { + for (const user of users) { + await usersRepository.update(user.id, { + updatedAt: new Date(0), + }); + } + } + + async function setSuspended(users: MiUser[]) { + for (const user of users) { + await usersRepository.update(user.id, { + isSuspended: true, + }); + } + } + + beforeAll(async () => { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + UserSearchService, + { + provide: UserEntityService, useFactory: jest.fn(() => ({ + // とりあえずIDが返れば確認が出来るので + packMany: (value: any) => value, + })), + }, + IdService, + ], + }) + .compile(); + + await app.init(); + + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + followingsRepository = app.get(DI.followingsRepository); + + service = app.get(UserSearchService); + idService = app.get(IdService); + }); + + beforeEach(async () => { + root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true }); + alice = await createUser({ username: 'Alice', usernameLower: 'alice' }); + alyce = await createUser({ username: 'Alyce', usernameLower: 'alyce' }); + alycia = await createUser({ username: 'Alycia', usernameLower: 'alycia' }); + alysha = await createUser({ username: 'Alysha', usernameLower: 'alysha' }); + alyson = await createUser({ username: 'Alyson', usernameLower: 'alyson', host: 'example.com' }); + alyssa = await createUser({ username: 'Alyssa', usernameLower: 'alyssa', host: 'example.com' }); + bob = await createUser({ username: 'Bob', usernameLower: 'bob' }); + bobbi = await createUser({ username: 'Bobbi', usernameLower: 'bobbi' }); + bobbie = await createUser({ username: 'Bobbie', usernameLower: 'bobbie', host: 'example.com' }); + bobby = await createUser({ username: 'Bobby', usernameLower: 'bobby', host: 'example.com' }); + }); + + afterEach(async () => { + await usersRepository.delete({}); + }); + + afterAll(async () => { + await app.close(); + }); + + describe('search', () => { + test('フォロー中のアクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await createFollowings(root, [alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setActive([alice, alyce, alyssa, bob, bobbi, bobbie, bobby]); + await setInactive([alycia, alysha, alyson]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + root, + ); + + // alycia, alysha, alysonは非アクティブなので後ろに行く + expect(result).toEqual([alice, alyce, alyssa, alycia, alysha, alyson].map(x => x.id)); + }); + + test('フォロー中の非アクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await createFollowings(root, [alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setInactive([alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + root, + ); + + // alice, alyceはフォローしていないので後ろに行く + expect(result).toEqual([alycia, alysha, alyson, alyssa, alice, alyce].map(x => x.id)); + }); + + test('フォローしていないアクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await setActive([alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setInactive([alice, alyce, alycia]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + root, + ); + + // alice, alyce, alyciaは非アクティブなので後ろに行く + expect(result).toEqual([alysha, alyson, alyssa, alice, alyce, alycia].map(x => x.id)); + }); + + test('フォローしていない非アクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await setInactive([alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + root, + ); + + expect(result).toEqual([alice, alyce, alycia, alysha, alyson, alyssa].map(x => x.id)); + }); + + test('フォロー(アクティブ)、フォロー(非アクティブ)、非フォロー(アクティブ)、非フォロー(非アクティブ)混在時の優先順位度確認', async () => { + await createFollowings(root, [alyson, alyssa, bob, bobbi, bobbie]); + await setActive([root, alyssa, bob, bobbi, alyce, alycia]); + await setInactive([alyson, alice, alysha, bobbie, bobby]); + + const result = await service.search( + { }, + { limit: 100 }, + root, + ); + + // 見る用 + // const users = await usersRepository.findBy({ id: In(result) }).then(it => new Map(it.map(x => [x.id, x]))); + // console.log(result.map(x => users.get(x as any)).map(it => it?.username)); + + // フォローしててアクティブなので先頭: alyssa, bob, bobbi + // フォローしてて非アクティブなので次: alyson, bobbie + // フォローしてないけどアクティブなので次: alyce, alycia, root(アルファベット順的にここになる) + // フォローしてないし非アクティブなので最後: alice, alysha, bobby + expect(result).toEqual([alyssa, bob, bobbi, alyson, bobbie, alyce, alycia, root, alice, alysha, bobby].map(x => x.id)); + }); + + test('[非ログイン] アクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await setActive([alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setInactive([alice, alyce, alycia]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + ); + + // alice, alyce, alyciaは非アクティブなので後ろに行く + expect(result).toEqual([alysha, alyson, alyssa, alice, alyce, alycia].map(x => x.id)); + }); + + test('[非ログイン] 非アクティブユーザのうち、"al"から始まる人が全員ヒットする', async () => { + await setInactive([alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + ); + + expect(result).toEqual([alice, alyce, alycia, alysha, alyson, alyssa].map(x => x.id)); + }); + + test('フォロー中のアクティブユーザのうち、"al"から始まり"example.com"にいる人が全員ヒットする', async () => { + await createFollowings(root, [alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setActive([alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + + const result = await service.search( + { username: 'al', host: 'exam' }, + { limit: 100 }, + root, + ); + + expect(result).toEqual([alyson, alyssa].map(x => x.id)); + }); + + test('サスペンド済みユーザは出ない', async () => { + await setActive([alice, alyce, alycia, alysha, alyson, alyssa, bob, bobbi, bobbie, bobby]); + await setSuspended([alice, alyce, alycia]); + + const result = await service.search( + { username: 'al' }, + { limit: 100 }, + root, + ); + + expect(result).toEqual([alysha, alyson, alyssa].map(x => x.id)); + }); + }); +}); diff --git a/packages/backend/test/unit/UserWebhookService.ts b/packages/backend/test/unit/UserWebhookService.ts new file mode 100644 index 0000000000..0e88835a02 --- /dev/null +++ b/packages/backend/test/unit/UserWebhookService.ts @@ -0,0 +1,245 @@ + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals'; +import { Test, TestingModule } from '@nestjs/testing'; +import { randomString } from '../utils.js'; +import { MiUser } from '@/models/User.js'; +import { MiWebhook, UsersRepository, WebhooksRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { DI } from '@/di-symbols.js'; +import { QueueService } from '@/core/QueueService.js'; +import { LoggerService } from '@/core/LoggerService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; + +describe('UserWebhookService', () => { + let app: TestingModule; + let service: UserWebhookService; + + // -------------------------------------------------------------------------------------- + + let usersRepository: UsersRepository; + let userWebhooksRepository: WebhooksRepository; + let idService: IdService; + let queueService: jest.Mocked; + + // -------------------------------------------------------------------------------------- + + let root: MiUser; + + // -------------------------------------------------------------------------------------- + + async function createUser(data: Partial = {}) { + return await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + } + + async function createWebhook(data: Partial = {}) { + return userWebhooksRepository + .insert({ + id: idService.gen(), + name: randomString(), + on: ['mention'], + url: 'https://example.com', + secret: randomString(), + userId: root.id, + ...data, + }) + .then(x => userWebhooksRepository.findOneByOrFail(x.identifiers[0])); + } + + // -------------------------------------------------------------------------------------- + + async function beforeAllImpl() { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + UserWebhookService, + IdService, + LoggerService, + GlobalEventService, + { + provide: QueueService, useFactory: () => ({ systemWebhookDeliver: jest.fn() }), + }, + ], + }) + .compile(); + + usersRepository = app.get(DI.usersRepository); + userWebhooksRepository = app.get(DI.webhooksRepository); + + service = app.get(UserWebhookService); + idService = app.get(IdService); + queueService = app.get(QueueService) as jest.Mocked; + + app.enableShutdownHooks(); + } + + async function afterAllImpl() { + await app.close(); + } + + async function beforeEachImpl() { + root = await createUser({ isRoot: true, username: 'root', usernameLower: 'root' }); + } + + async function afterEachImpl() { + await usersRepository.delete({}); + await userWebhooksRepository.delete({}); + } + + // -------------------------------------------------------------------------------------- + + describe('アプリを毎回作り直す必要のないグループ', () => { + beforeAll(beforeAllImpl); + afterAll(afterAllImpl); + beforeEach(beforeEachImpl); + afterEach(afterEachImpl); + + describe('fetchSystemWebhooks', () => { + test('フィルタなし', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks(); + expect(fetchedWebhooks).toEqual([webhook1, webhook2, webhook3, webhook4]); + }); + + test('activeのみ', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks({ isActive: true }); + expect(fetchedWebhooks).toEqual([webhook1, webhook3]); + }); + + test('特定のイベントのみ', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks({ on: ['mention'] }); + expect(fetchedWebhooks).toEqual([webhook1, webhook2]); + }); + + test('activeな特定のイベントのみ', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks({ on: ['mention'], isActive: true }); + expect(fetchedWebhooks).toEqual([webhook1]); + }); + + test('ID指定', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks({ ids: [webhook1.id, webhook4.id] }); + expect(fetchedWebhooks).toEqual([webhook1, webhook4]); + }); + + test('ID指定(他条件とANDになるか見たい)', async () => { + const webhook1 = await createWebhook({ + active: true, + on: ['mention'], + }); + const webhook2 = await createWebhook({ + active: false, + on: ['mention'], + }); + const webhook3 = await createWebhook({ + active: true, + on: ['reply'], + }); + const webhook4 = await createWebhook({ + active: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchWebhooks({ ids: [webhook1.id, webhook4.id], isActive: false }); + expect(fetchedWebhooks).toEqual([webhook4]); + }); + }); + }); +}); diff --git a/packages/backend/test/unit/WebhookTestService.ts b/packages/backend/test/unit/WebhookTestService.ts new file mode 100644 index 0000000000..5e63b86f8f --- /dev/null +++ b/packages/backend/test/unit/WebhookTestService.ts @@ -0,0 +1,225 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Test, TestingModule } from '@nestjs/testing'; +import { beforeAll, describe, jest } from '@jest/globals'; +import { WebhookTestService } from '@/core/WebhookTestService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { MiSystemWebhook, MiUser, MiWebhook, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { DI } from '@/di-symbols.js'; +import { QueueService } from '@/core/QueueService.js'; + +describe('WebhookTestService', () => { + let app: TestingModule; + let service: WebhookTestService; + + // -------------------------------------------------------------------------------------- + + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + let queueService: jest.Mocked; + let userWebhookService: jest.Mocked; + let systemWebhookService: jest.Mocked; + let idService: IdService; + + let root: MiUser; + let alice: MiUser; + + async function createUser(data: Partial = {}) { + const user = await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.insert({ + userId: user.id, + }); + + return user; + } + + // -------------------------------------------------------------------------------------- + + beforeAll(async () => { + app = await Test.createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + WebhookTestService, + IdService, + { + provide: QueueService, useFactory: () => ({ + systemWebhookDeliver: jest.fn(), + userWebhookDeliver: jest.fn(), + }), + }, + { + provide: UserWebhookService, useFactory: () => ({ + fetchWebhooks: jest.fn(), + }), + }, + { + provide: SystemWebhookService, useFactory: () => ({ + fetchSystemWebhooks: jest.fn(), + }), + }, + ], + }).compile(); + + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + + service = app.get(WebhookTestService); + idService = app.get(IdService); + queueService = app.get(QueueService) as jest.Mocked; + userWebhookService = app.get(UserWebhookService) as jest.Mocked; + systemWebhookService = app.get(SystemWebhookService) as jest.Mocked; + + app.enableShutdownHooks(); + }); + + beforeEach(async () => { + root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true }); + alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false }); + + userWebhookService.fetchWebhooks.mockReturnValue(Promise.resolve([ + { id: 'dummy-webhook', active: true, userId: alice.id } as MiWebhook, + ])); + systemWebhookService.fetchSystemWebhooks.mockReturnValue(Promise.resolve([ + { id: 'dummy-webhook', isActive: true } as MiSystemWebhook, + ])); + }); + + afterEach(async () => { + queueService.systemWebhookDeliver.mockClear(); + queueService.userWebhookDeliver.mockClear(); + userWebhookService.fetchWebhooks.mockClear(); + systemWebhookService.fetchSystemWebhooks.mockClear(); + + await usersRepository.delete({}); + await userProfilesRepository.delete({}); + }); + + afterAll(async () => { + await app.close(); + }); + + // -------------------------------------------------------------------------------------- + + describe('testUserWebhook', () => { + test('note', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'note' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('note'); + expect((calls[2] as any).id).toBe('dummy-note-1'); + }); + + test('reply', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'reply' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('reply'); + expect((calls[2] as any).id).toBe('dummy-reply-1'); + }); + + test('renote', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'renote' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('renote'); + expect((calls[2] as any).id).toBe('dummy-renote-1'); + }); + + test('mention', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'mention' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('mention'); + expect((calls[2] as any).id).toBe('dummy-mention-1'); + }); + + test('follow', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'follow' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('follow'); + expect((calls[2] as any).id).toBe('dummy-user-1'); + }); + + test('followed', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'followed' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('followed'); + expect((calls[2] as any).id).toBe('dummy-user-2'); + }); + + test('unfollow', async () => { + await service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'unfollow' }, alice); + + const calls = queueService.userWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('unfollow'); + expect((calls[2] as any).id).toBe('dummy-user-3'); + }); + + describe('NoSuchWebhookError', () => { + test('user not match', async () => { + userWebhookService.fetchWebhooks.mockClear(); + userWebhookService.fetchWebhooks.mockReturnValue(Promise.resolve([ + { id: 'dummy-webhook', active: true } as MiWebhook, + ])); + + await expect(service.testUserWebhook({ webhookId: 'dummy-webhook', type: 'note' }, root)) + .rejects.toThrow(WebhookTestService.NoSuchWebhookError); + }); + }); + }); + + describe('testSystemWebhook', () => { + test('abuseReport', async () => { + await service.testSystemWebhook({ webhookId: 'dummy-webhook', type: 'abuseReport' }); + + const calls = queueService.systemWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('abuseReport'); + expect((calls[2] as any).id).toBe('dummy-abuse-report1'); + expect((calls[2] as any).resolved).toBe(false); + }); + + test('abuseReportResolved', async () => { + await service.testSystemWebhook({ webhookId: 'dummy-webhook', type: 'abuseReportResolved' }); + + const calls = queueService.systemWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('abuseReportResolved'); + expect((calls[2] as any).id).toBe('dummy-abuse-report1'); + expect((calls[2] as any).resolved).toBe(true); + }); + + test('userCreated', async () => { + await service.testSystemWebhook({ webhookId: 'dummy-webhook', type: 'userCreated' }); + + const calls = queueService.systemWebhookDeliver.mock.calls[0]; + expect((calls[0] as any).id).toBe('dummy-webhook'); + expect(calls[1]).toBe('userCreated'); + expect((calls[2] as any).id).toBe('dummy-user-1'); + }); + }); +}); diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts index 6962608106..2fc08aec91 100644 --- a/packages/backend/test/unit/activitypub.ts +++ b/packages/backend/test/unit/activitypub.ts @@ -20,10 +20,10 @@ import { CoreModule } from '@/core/CoreModule.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { LoggerService } from '@/core/LoggerService.js'; import type { IActor, IApDocument, ICollection, IObject, IPost } from '@/core/activitypub/type.js'; -import { MiMeta, MiNote } from '@/models/_.js'; +import { MiMeta, MiNote, UserProfilesRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { DownloadService } from '@/core/DownloadService.js'; -import { MetaService } from '@/core/MetaService.js'; import type { MiRemoteUser } from '@/models/User.js'; import { genAidx } from '@/misc/id/aidx.js'; import { MockResolver } from '../misc/mock-resolver.js'; @@ -86,6 +86,7 @@ async function createRandomRemoteUser( } describe('ActivityPub', () => { + let userProfilesRepository: UserProfilesRepository; let imageService: ApImageService; let noteService: ApNoteService; let personService: ApPersonService; @@ -105,7 +106,14 @@ describe('ActivityPub', () => { sensitiveWords: [] as string[], prohibitedWords: [] as string[], } as MiMeta; - let meta = metaInitial; + const meta = { ...metaInitial }; + + function updateMeta(newMeta: Partial): void { + for (const key in meta) { + delete (meta as any)[key]; + } + Object.assign(meta, newMeta); + } beforeAll(async () => { const app = await Test.createTestingModule({ @@ -118,15 +126,14 @@ describe('ActivityPub', () => { }; }, }) - .overrideProvider(MetaService).useValue({ - async fetch(): Promise { - return meta; - }, - }).compile(); + .overrideProvider(DI.meta).useFactory({ factory: () => meta }) + .compile(); await app.init(); app.enableShutdownHooks(); + userProfilesRepository = app.get(DI.userProfilesRepository); + noteService = app.get(ApNoteService); personService = app.get(ApPersonService); rendererService = app.get(ApRendererService); @@ -205,6 +212,53 @@ describe('ActivityPub', () => { }); }); + describe('Collection visibility', () => { + test('Public following/followers', async () => { + const actor = createRandomActor(); + actor.following = { + id: `${actor.id}/following`, + type: 'OrderedCollection', + totalItems: 0, + first: `${actor.id}/following?page=1`, + }; + actor.followers = `${actor.id}/followers`; + + resolver.register(actor.id, actor); + resolver.register(actor.followers, { + id: actor.followers, + type: 'OrderedCollection', + totalItems: 0, + first: `${actor.followers}?page=1`, + }); + + const user = await personService.createPerson(actor.id, resolver); + const userProfile = await userProfilesRepository.findOneByOrFail({ userId: user.id }); + + assert.deepStrictEqual(userProfile.followingVisibility, 'public'); + assert.deepStrictEqual(userProfile.followersVisibility, 'public'); + }); + + test('Private following/followers', async () => { + const actor = createRandomActor(); + actor.following = { + id: `${actor.id}/following`, + type: 'OrderedCollection', + totalItems: 0, + // first: … + }; + actor.followers = `${actor.id}/followers`; + + resolver.register(actor.id, actor); + //resolver.register(actor.followers, { … }); + + const user = await personService.createPerson(actor.id, resolver); + const userProfile = await userProfilesRepository.findOneByOrFail({ userId: user.id }); + + assert.deepStrictEqual(userProfile.followingVisibility, 'private'); + assert.deepStrictEqual(userProfile.followersVisibility, 'private'); + }); + }); + describe('Renderer', () => { test('Render an announce with visibility: followers', () => { rendererService.renderAnnounce('https://example.com/notes/00example', { @@ -316,7 +370,7 @@ describe('ActivityPub', () => { }); test('cacheRemoteFiles=false disables caching', async () => { - meta = { ...metaInitial, cacheRemoteFiles: false }; + updateMeta({ ...metaInitial, cacheRemoteFiles: false }); const imageObject: IApDocument = { type: 'Document', @@ -345,7 +399,7 @@ describe('ActivityPub', () => { }); test('cacheRemoteSensitiveFiles=false only affects sensitive files', async () => { - meta = { ...metaInitial, cacheRemoteSensitiveFiles: false }; + updateMeta({ ...metaInitial, cacheRemoteSensitiveFiles: false }); const imageObject: IApDocument = { type: 'Document', diff --git a/packages/backend/test/unit/entities/UserEntityService.ts b/packages/backend/test/unit/entities/UserEntityService.ts index ee16d421c4..e4f42809f8 100644 --- a/packages/backend/test/unit/entities/UserEntityService.ts +++ b/packages/backend/test/unit/entities/UserEntityService.ts @@ -4,10 +4,10 @@ */ import { Test, TestingModule } from '@nestjs/testing'; +import type { MiUser } from '@/models/User.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalModule } from '@/GlobalModule.js'; import { CoreModule } from '@/core/CoreModule.js'; -import type { MiUser } from '@/models/User.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { genAidx } from '@/misc/id/aidx.js'; import { @@ -49,6 +49,7 @@ import { ApLoggerService } from '@/core/activitypub/ApLoggerService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; import { ReactionService } from '@/core/ReactionService.js'; import { NotificationService } from '@/core/NotificationService.js'; +import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js'; process.env.NODE_ENV = 'test'; @@ -169,6 +170,7 @@ describe('UserEntityService', () => { ApLoggerService, AccountMoveService, ReactionService, + ReactionsBufferingService, NotificationService, ]; diff --git a/packages/backend/test/unit/queue/processors/CheckModeratorsActivityProcessorService.ts b/packages/backend/test/unit/queue/processors/CheckModeratorsActivityProcessorService.ts new file mode 100644 index 0000000000..b783320aa0 --- /dev/null +++ b/packages/backend/test/unit/queue/processors/CheckModeratorsActivityProcessorService.ts @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { jest } from '@jest/globals'; +import { Test, TestingModule } from '@nestjs/testing'; +import * as lolex from '@sinonjs/fake-timers'; +import { addHours, addSeconds, subDays, subHours, subSeconds } from 'date-fns'; +import { CheckModeratorsActivityProcessorService } from '@/queue/processors/CheckModeratorsActivityProcessorService.js'; +import { MiUser, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { RoleService } from '@/core/RoleService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { MetaService } from '@/core/MetaService.js'; +import { DI } from '@/di-symbols.js'; +import { QueueLoggerService } from '@/queue/QueueLoggerService.js'; + +const baseDate = new Date(Date.UTC(2000, 11, 15, 12, 0, 0)); + +describe('CheckModeratorsActivityProcessorService', () => { + let app: TestingModule; + let clock: lolex.InstalledClock; + let service: CheckModeratorsActivityProcessorService; + + // -------------------------------------------------------------------------------------- + + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + let idService: IdService; + let roleService: jest.Mocked; + + // -------------------------------------------------------------------------------------- + + async function createUser(data: Partial = {}) { + const id = idService.gen(); + const user = await usersRepository + .insert({ + id: id, + username: `user_${id}`, + usernameLower: `user_${id}`.toLowerCase(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.insert({ + userId: user.id, + }); + + return user; + } + + function mockModeratorRole(users: MiUser[]) { + roleService.getModerators.mockReset(); + roleService.getModerators.mockResolvedValue(users); + } + + // -------------------------------------------------------------------------------------- + + beforeAll(async () => { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + CheckModeratorsActivityProcessorService, + IdService, + { + provide: RoleService, useFactory: () => ({ getModerators: jest.fn() }), + }, + { + provide: MetaService, useFactory: () => ({ fetch: jest.fn() }), + }, + { + provide: QueueLoggerService, useFactory: () => ({ + logger: ({ + createSubLogger: () => ({ + info: jest.fn(), + warn: jest.fn(), + succ: jest.fn(), + }), + }), + }), + }, + ], + }) + .compile(); + + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + + service = app.get(CheckModeratorsActivityProcessorService); + idService = app.get(IdService); + roleService = app.get(RoleService) as jest.Mocked; + + app.enableShutdownHooks(); + }); + + beforeEach(async () => { + clock = lolex.install({ + now: new Date(baseDate), + shouldClearNativeTimers: true, + }); + }); + + afterEach(async () => { + clock.uninstall(); + await usersRepository.delete({}); + await userProfilesRepository.delete({}); + roleService.getModerators.mockReset(); + }); + + afterAll(async () => { + await app.close(); + }); + + // -------------------------------------------------------------------------------------- + + describe('evaluateModeratorsInactiveDays', () => { + test('[isModeratorsInactive] inactiveなモデレーターがいても他のモデレーターがアクティブなら"運営が非アクティブ"としてみなされない', async () => { + const [user1, user2, user3, user4] = await Promise.all([ + // 期限よりも1秒新しいタイミングでアクティブ化(セーフ) + createUser({ lastActiveDate: subDays(addSeconds(baseDate, 1), 7) }), + // 期限ちょうどにアクティブ化(セーフ) + createUser({ lastActiveDate: subDays(baseDate, 7) }), + // 期限よりも1秒古いタイミングでアクティブ化(アウト) + createUser({ lastActiveDate: subDays(subSeconds(baseDate, 1), 7) }), + // 対象外 + createUser({ lastActiveDate: null }), + ]); + + mockModeratorRole([user1, user2, user3, user4]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(false); + expect(result.inactiveModerators).toEqual([user3]); + }); + + test('[isModeratorsInactive] 全員非アクティブなら"運営が非アクティブ"としてみなされる', async () => { + const [user1, user2] = await Promise.all([ + // 期限よりも1秒古いタイミングでアクティブ化(アウト) + createUser({ lastActiveDate: subDays(subSeconds(baseDate, 1), 7) }), + // 対象外 + createUser({ lastActiveDate: null }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(true); + expect(result.inactiveModerators).toEqual([user1]); + }); + + test('[countdown] 猶予まで24時間ある場合、猶予1日として計算される', async () => { + const [user1, user2] = await Promise.all([ + createUser({ lastActiveDate: subDays(baseDate, 8) }), + // 猶予はこのユーザ基準で計算される想定。 + // 期限まで残り24時間->猶予1日として計算されるはずである + createUser({ lastActiveDate: subDays(baseDate, 6) }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(false); + expect(result.inactiveModerators).toEqual([user1]); + expect(result.inactivityLimitCountdown).toBe(1); + }); + + test('[countdown] 猶予まで25時間ある場合、猶予1日として計算される', async () => { + const [user1, user2] = await Promise.all([ + createUser({ lastActiveDate: subDays(baseDate, 8) }), + // 猶予はこのユーザ基準で計算される想定。 + // 期限まで残り25時間->猶予1日として計算されるはずである + createUser({ lastActiveDate: subDays(addHours(baseDate, 1), 6) }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(false); + expect(result.inactiveModerators).toEqual([user1]); + expect(result.inactivityLimitCountdown).toBe(1); + }); + + test('[countdown] 猶予まで23時間ある場合、猶予0日として計算される', async () => { + const [user1, user2] = await Promise.all([ + createUser({ lastActiveDate: subDays(baseDate, 8) }), + // 猶予はこのユーザ基準で計算される想定。 + // 期限まで残り23時間->猶予0日として計算されるはずである + createUser({ lastActiveDate: subDays(subHours(baseDate, 1), 6) }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(false); + expect(result.inactiveModerators).toEqual([user1]); + expect(result.inactivityLimitCountdown).toBe(0); + }); + + test('[countdown] 期限ちょうどの場合、猶予0日として計算される', async () => { + const [user1, user2] = await Promise.all([ + createUser({ lastActiveDate: subDays(baseDate, 8) }), + // 猶予はこのユーザ基準で計算される想定。 + // 期限ちょうど->猶予0日として計算されるはずである + createUser({ lastActiveDate: subDays(baseDate, 7) }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(false); + expect(result.inactiveModerators).toEqual([user1]); + expect(result.inactivityLimitCountdown).toBe(0); + }); + + test('[countdown] 期限より1時間超過している場合、猶予-1日として計算される', async () => { + const [user1, user2] = await Promise.all([ + createUser({ lastActiveDate: subDays(baseDate, 8) }), + // 猶予はこのユーザ基準で計算される想定。 + // 期限より1時間超過->猶予-1日として計算されるはずである + createUser({ lastActiveDate: subDays(subHours(baseDate, 1), 7) }), + ]); + + mockModeratorRole([user1, user2]); + + const result = await service.evaluateModeratorsInactiveDays(); + expect(result.isModeratorsInactive).toBe(true); + expect(result.inactiveModerators).toEqual([user1, user2]); + expect(result.inactivityLimitCountdown).toBe(-1); + }); + }); +}); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index aad4ab37c9..26de19eaf1 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -12,12 +12,14 @@ import WebSocket, { ClientOptions } from 'ws'; import fetch, { File, RequestInit, type Headers } from 'node-fetch'; import { DataSource } from 'typeorm'; import { JSDOM } from 'jsdom'; -import { DEFAULT_POLICIES } from '@/core/RoleService.js'; -import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; +import { type Response } from 'node-fetch'; +import Fastify from 'fastify'; import { entities } from '../src/postgres.js'; import { loadConfig } from '../src/config.js'; import type * as misskey from 'misskey-js'; -import { type Response } from 'node-fetch'; +import { DEFAULT_POLICIES } from '@/core/RoleService.js'; +import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; +import { ApiError } from '@/server/api/error.js'; export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js'; @@ -26,11 +28,23 @@ export interface UserToken { bearer?: boolean; } +export type SystemWebhookPayload = { + server: string; + hookId: string; + eventId: string; + createdAt: string; + type: string; + body: any; +} + const config = loadConfig(); export const port = config.port; export const origin = config.url; export const host = new URL(config.url).host; +export const WEBHOOK_HOST = 'http://localhost:15080'; +export const WEBHOOK_PORT = 15080; + export const cookie = (me: UserToken): string => { return `token=${me.token};`; }; @@ -48,27 +62,28 @@ export const successfulApiCall = async ; }; -export const failedApiCall = async (request: ApiRequest, assertion: { +export const failedApiCall = async (request: ApiRequest, assertion: { status: number, code: string, id: string -}): Promise => { +}): Promise => { const { endpoint, parameters, user } = request; const { status, code, id } = assertion; const res = await api(endpoint, parameters, user); assert.strictEqual(res.status, status, inspect(res.body)); - assert.strictEqual(res.body.error.code, code, inspect(res.body)); - assert.strictEqual(res.body.error.id, id, inspect(res.body)); - return res.body; + assert.ok(res.body); + assert.strictEqual(castAsError(res.body as any).error.code, code, inspect(res.body)); + assert.strictEqual(castAsError(res.body as any).error.id, id, inspect(res.body)); }; -export const api = async (path: E, params: misskey.Endpoints[E]['req'], me?: UserToken): Promise<{ +export const api = async (path: E, params: P, me?: UserToken): Promise<{ status: number, headers: Headers, - body: any + body: misskey.api.SwitchCaseResponseType }> => { const bodyAuth: Record = {}; const headers: Record = { @@ -89,13 +104,14 @@ export const api = async (path: E, params: mi }); const body = res.headers.get('content-type') === 'application/json; charset=utf-8' - ? await res.json() + ? await res.json() as misskey.api.SwitchCaseResponseType : null; return { status: res.status, headers: res.headers, - body, + // FIXME: removing this non-null assertion: requires better typing around empty response. + body: body!, }; }; @@ -141,7 +157,8 @@ export const post = async (user: UserToken, params: misskey.Endpoints['notes/cre const res = await api('notes/create', q, user); - return res.body ? res.body.createdNote : null; + // FIXME: the return type should reflect this fact. + return (res.body ? res.body.createdNote : null)!; }; export const createAppToken = async (user: UserToken, permissions: (typeof misskey.permissions)[number][]) => { @@ -297,7 +314,7 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO body: misskey.entities.DriveFile | null }> => { const absPath = path == null - ? new URL('resources/Lenna.jpg', import.meta.url) + ? new URL('resources/192.jpg', import.meta.url) : isAbsolute(path.toString()) ? new URL(path) : new URL(path, new URL('resources/', import.meta.url)); @@ -605,14 +622,6 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) { return db; } -export function sleep(msec: number) { - return new Promise(res => { - setTimeout(() => { - res(); - }, msec); - }); -} - export async function sendEnvUpdateRequest(params: { key: string, value?: string }) { const res = await fetch( `http://localhost:${port + 1000}/env`, @@ -643,3 +652,43 @@ export async function sendEnvResetRequest() { throw new Error('server env update failed.'); } } + +// 与えられた値を強制的にエラーとみなす。この関数は型安全性を破壊するため、異常系のアサーション以外で用いられるべきではない。 +// FIXME(misskey-js): misskey-jsがエラー情報を公開するようになったらこの関数を廃止する +export function castAsError(obj: Record): { error: ApiError } { + return obj as { error: ApiError }; +} + +export async function captureWebhook(postAction: () => Promise, port = WEBHOOK_PORT): Promise { + const fastify = Fastify(); + + let timeoutHandle: NodeJS.Timeout | null = null; + const result = await new Promise(async (resolve, reject) => { + fastify.all('/', async (req, res) => { + timeoutHandle && clearTimeout(timeoutHandle); + + const body = JSON.stringify(req.body); + res.status(200).send('ok'); + await fastify.close(); + resolve(body); + }); + + await fastify.listen({ port }); + + timeoutHandle = setTimeout(async () => { + await fastify.close(); + reject(new Error('timeout')); + }, 3000); + + try { + await postAction(); + } catch (e) { + await fastify.close(); + reject(e); + } + }); + + await fastify.close(); + + return JSON.parse(result) as T; +} diff --git a/packages/frontend-embed/.gitignore b/packages/frontend-embed/.gitignore new file mode 100644 index 0000000000..1aa0ac14e8 --- /dev/null +++ b/packages/frontend-embed/.gitignore @@ -0,0 +1 @@ +/storybook-static diff --git a/packages/frontend-embed/@types/global.d.ts b/packages/frontend-embed/@types/global.d.ts new file mode 100644 index 0000000000..1025d1bedb --- /dev/null +++ b/packages/frontend-embed/@types/global.d.ts @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +type FIXME = any; + +declare const _LANGS_: string[][]; +declare const _VERSION_: string; +declare const _ENV_: string; +declare const _DEV_: boolean; +declare const _PERF_PREFIX_: string; +declare const _DATA_TRANSFER_DRIVE_FILE_: string; +declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; +declare const _DATA_TRANSFER_DECK_COLUMN_: string; + +// for dev-mode +declare const _LANGS_FULL_: string[][]; + +// TagCanvas +interface Window { + TagCanvas: any; +} diff --git a/packages/frontend-embed/@types/theme.d.ts b/packages/frontend-embed/@types/theme.d.ts new file mode 100644 index 0000000000..6ac1037493 --- /dev/null +++ b/packages/frontend-embed/@types/theme.d.ts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +declare module '@@/themes/*.json5' { + import { Theme } from '@/theme.js'; + + const theme: Theme; + + export default theme; +} diff --git a/packages/frontend-embed/assets/dummy.png b/packages/frontend-embed/assets/dummy.png new file mode 100644 index 0000000000000000000000000000000000000000..39332b0c1beeda1edb90d78d25c16e7372aff030 GIT binary patch literal 6285 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 s [key, 'off'])), + ...globals.browser, + + // Node.js + module: false, + require: false, + __dirname: false, + + // Misskey + _DEV_: false, + _LANGS_: false, + _VERSION_: false, + _ENV_: false, + _PERF_PREFIX_: false, + _DATA_TRANSFER_DRIVE_FILE_: false, + _DATA_TRANSFER_DRIVE_FOLDER_: false, + _DATA_TRANSFER_DECK_COLUMN_: false, + }, + parser, + parserOptions: { + extraFileExtensions: ['.vue'], + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-empty-interface': ['error', { + allowSingleExtends: true, + }], + // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため + // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため + 'id-denylist': ['error', 'window', 'e'], + 'no-shadow': ['warn'], + 'vue/attributes-order': ['error', { + alphabetical: false, + }], + 'vue/no-use-v-if-with-v-for': ['error', { + allowUsingIterationVar: false, + }], + 'vue/no-ref-as-operand': 'error', + 'vue/no-multi-spaces': ['error', { + ignoreProperties: false, + }], + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'error', + 'vue/html-indent': ['warn', 'tab', { + attribute: 1, + baseIndent: 0, + closeBracket: 0, + alignAttributesVertically: true, + ignores: [], + }], + 'vue/html-closing-bracket-spacing': ['warn', { + startTag: 'never', + endTag: 'never', + selfClosingTag: 'never', + }], + 'vue/multi-word-component-names': 'warn', + 'vue/require-v-for-key': 'warn', + 'vue/no-unused-components': 'warn', + 'vue/no-unused-vars': 'warn', + 'vue/no-dupe-keys': 'warn', + 'vue/valid-v-for': 'warn', + 'vue/return-in-computed-property': 'warn', + 'vue/no-setup-props-reactivity-loss': 'warn', + 'vue/max-attributes-per-line': 'off', + 'vue/html-self-closing': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/v-on-event-hyphenation': ['error', 'never', { + autofix: true, + }], + 'vue/attribute-hyphenation': ['error', 'never'], + }, + }, +]; diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json new file mode 100644 index 0000000000..cb62191c3b --- /dev/null +++ b/packages/frontend-embed/package.json @@ -0,0 +1,72 @@ +{ + "name": "frontend-embed", + "private": true, + "type": "module", + "scripts": { + "watch": "vite", + "dev": "vite --config vite.config.local-dev.ts --debug hmr", + "build": "vite build", + "typecheck": "vue-tsc --noEmit", + "eslint": "eslint --quiet \"src/**/*.{ts,vue}\"", + "lint": "pnpm typecheck && pnpm eslint" + }, + "dependencies": { + "@discordapp/twemoji": "15.1.0", + "@rollup/plugin-json": "6.1.0", + "@rollup/plugin-replace": "5.0.7", + "@rollup/pluginutils": "5.1.2", + "@tabler/icons-webfont": "3.3.0", + "@twemoji/parser": "15.1.1", + "@vitejs/plugin-vue": "5.1.4", + "@vue/compiler-sfc": "3.5.11", + "astring": "1.9.0", + "buraha": "0.0.1", + "estree-walker": "3.0.3", + "mfm-js": "0.24.0", + "misskey-js": "workspace:*", + "frontend-shared": "workspace:*", + "punycode": "2.3.1", + "rollup": "4.22.5", + "sass": "1.79.4", + "shiki": "1.21.0", + "tinycolor2": "1.6.0", + "tsc-alias": "1.8.10", + "tsconfig-paths": "4.2.0", + "typescript": "5.6.2", + "uuid": "10.0.0", + "json5": "2.2.3", + "vite": "5.4.8", + "vue": "3.5.11" + }, + "devDependencies": { + "@misskey-dev/summaly": "5.1.0", + "@testing-library/vue": "8.1.0", + "@types/estree": "1.0.6", + "@types/micromatch": "4.0.9", + "@types/node": "20.14.12", + "@types/punycode": "2.1.4", + "@types/tinycolor2": "1.4.6", + "@types/uuid": "10.0.0", + "@types/ws": "8.5.12", + "@typescript-eslint/eslint-plugin": "7.17.0", + "@typescript-eslint/parser": "7.17.0", + "@vitest/coverage-v8": "1.6.0", + "@vue/runtime-core": "3.5.11", + "acorn": "8.12.1", + "cross-env": "7.0.3", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-vue": "9.28.0", + "fast-glob": "3.3.2", + "happy-dom": "10.0.3", + "intersection-observer": "0.12.2", + "micromatch": "4.0.8", + "msw": "2.3.4", + "nodemon": "3.1.7", + "prettier": "3.3.3", + "start-server-and-test": "2.0.8", + "vite-plugin-turbosnap": "1.0.3", + "vue-component-type-helpers": "2.1.6", + "vue-eslint-parser": "9.4.3", + "vue-tsc": "2.1.6" + } +} diff --git a/packages/frontend-embed/src/boot.ts b/packages/frontend-embed/src/boot.ts new file mode 100644 index 0000000000..00c7944eb3 --- /dev/null +++ b/packages/frontend-embed/src/boot.ts @@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +// https://vitejs.dev/config/build-options.html#build-modulepreload +import 'vite/modulepreload-polyfill'; + +import '@tabler/icons-webfont/dist/tabler-icons.scss'; + +import '@/style.scss'; +import { createApp, defineAsyncComponent } from 'vue'; +import defaultLightTheme from '@@/themes/l-light.json5'; +import defaultDarkTheme from '@@/themes/d-dark.json5'; +import { MediaProxy } from '@@/js/media-proxy.js'; +import { applyTheme, assertIsTheme } from '@/theme.js'; +import { fetchCustomEmojis } from '@/custom-emojis.js'; +import { DI } from '@/di.js'; +import { serverMetadata } from '@/server-metadata.js'; +import { url } from '@@/js/config.js'; +import { parseEmbedParams } from '@@/js/embed-page.js'; +import { postMessageToParentWindow, setIframeId } from '@/post-message.js'; +import { serverContext } from '@/server-context.js'; + +import type { Theme } from '@/theme.js'; + +console.log('Misskey Embed'); + +//#region Embedパラメータの取得・パース +const params = new URLSearchParams(location.search); +const embedParams = parseEmbedParams(params); +if (_DEV_) console.log(embedParams); +//#endregion + +//#region テーマ +function parseThemeOrNull(theme: string | null): Theme | null { + if (theme == null) return null; + try { + const parsed = JSON.parse(theme); + if (assertIsTheme(parsed)) { + return parsed; + } else { + return null; + } + } catch (err) { + return null; + } +} + +const lightTheme = parseThemeOrNull(serverMetadata.defaultLightTheme) ?? defaultLightTheme; +const darkTheme = parseThemeOrNull(serverMetadata.defaultDarkTheme) ?? defaultDarkTheme; + +if (embedParams.colorMode === 'dark') { + applyTheme(darkTheme); +} else if (embedParams.colorMode === 'light') { + applyTheme(lightTheme); +} else { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + applyTheme(darkTheme); + } else { + applyTheme(lightTheme); + } + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (mql) => { + if (mql.matches) { + applyTheme(darkTheme); + } else { + applyTheme(lightTheme); + } + }); +} +//#endregion + +// サイズの制限 +document.documentElement.style.maxWidth = '500px'; + +// iframeIdの設定 +function setIframeIdHandler(event: MessageEvent) { + if (event.data?.type === 'misskey:embedParent:registerIframeId' && event.data.payload?.iframeId != null) { + setIframeId(event.data.payload.iframeId); + window.removeEventListener('message', setIframeIdHandler); + } +} + +window.addEventListener('message', setIframeIdHandler); + +try { + await fetchCustomEmojis(); +} catch (err) { /* empty */ } + +const app = createApp( + defineAsyncComponent(() => import('@/ui.vue')), +); + +app.provide(DI.mediaProxy, new MediaProxy(serverMetadata, url)); + +app.provide(DI.serverMetadata, serverMetadata); + +app.provide(DI.serverContext, serverContext); + +app.provide(DI.embedParams, embedParams); + +// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210 +// なぜか2回実行されることがあるため、mountするdivを1つに制限する +const rootEl = ((): HTMLElement => { + const MISSKEY_MOUNT_DIV_ID = 'misskey_app'; + + const currentRoot = document.getElementById(MISSKEY_MOUNT_DIV_ID); + + if (currentRoot) { + console.warn('multiple import detected'); + return currentRoot; + } + + const root = document.createElement('div'); + root.id = MISSKEY_MOUNT_DIV_ID; + document.body.appendChild(root); + return root; +})(); + +postMessageToParentWindow('misskey:embed:ready'); + +app.mount(rootEl); + +// boot.jsのやつを解除 +window.onerror = null; +window.onunhandledrejection = null; + +removeSplash(); + +function removeSplash() { + const splash = document.getElementById('splash'); + if (splash) { + splash.style.opacity = '0'; + splash.style.pointerEvents = 'none'; + + // transitionendイベントが発火しない場合があるため + window.setTimeout(() => { + splash.remove(); + }, 1000); + } +} diff --git a/packages/frontend-embed/src/components/EmA.vue b/packages/frontend-embed/src/components/EmA.vue new file mode 100644 index 0000000000..1c236b9a35 --- /dev/null +++ b/packages/frontend-embed/src/components/EmA.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/packages/frontend-embed/src/components/EmAcct.vue b/packages/frontend-embed/src/components/EmAcct.vue new file mode 100644 index 0000000000..6856b8272e --- /dev/null +++ b/packages/frontend-embed/src/components/EmAcct.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/frontend-embed/src/components/EmAvatar.vue b/packages/frontend-embed/src/components/EmAvatar.vue new file mode 100644 index 0000000000..58c35c8ef0 --- /dev/null +++ b/packages/frontend-embed/src/components/EmAvatar.vue @@ -0,0 +1,250 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmCustomEmoji.vue b/packages/frontend-embed/src/components/EmCustomEmoji.vue new file mode 100644 index 0000000000..59b670cdc6 --- /dev/null +++ b/packages/frontend-embed/src/components/EmCustomEmoji.vue @@ -0,0 +1,99 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmEmoji.vue b/packages/frontend-embed/src/components/EmEmoji.vue new file mode 100644 index 0000000000..224979707b --- /dev/null +++ b/packages/frontend-embed/src/components/EmEmoji.vue @@ -0,0 +1,26 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmError.vue b/packages/frontend-embed/src/components/EmError.vue new file mode 100644 index 0000000000..d376b29a7f --- /dev/null +++ b/packages/frontend-embed/src/components/EmError.vue @@ -0,0 +1,43 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmImgWithBlurhash.vue b/packages/frontend-embed/src/components/EmImgWithBlurhash.vue new file mode 100644 index 0000000000..bf976c71ae --- /dev/null +++ b/packages/frontend-embed/src/components/EmImgWithBlurhash.vue @@ -0,0 +1,240 @@ + + + + + + + + + diff --git a/packages/frontend-embed/src/components/EmInstanceTicker.vue b/packages/frontend-embed/src/components/EmInstanceTicker.vue new file mode 100644 index 0000000000..4a116e317a --- /dev/null +++ b/packages/frontend-embed/src/components/EmInstanceTicker.vue @@ -0,0 +1,87 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmLink.vue b/packages/frontend-embed/src/components/EmLink.vue new file mode 100644 index 0000000000..aec9b33072 --- /dev/null +++ b/packages/frontend-embed/src/components/EmLink.vue @@ -0,0 +1,40 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmLoading.vue b/packages/frontend-embed/src/components/EmLoading.vue new file mode 100644 index 0000000000..47d797606b --- /dev/null +++ b/packages/frontend-embed/src/components/EmLoading.vue @@ -0,0 +1,112 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMediaBanner.vue b/packages/frontend-embed/src/components/EmMediaBanner.vue new file mode 100644 index 0000000000..cf4a4c53b5 --- /dev/null +++ b/packages/frontend-embed/src/components/EmMediaBanner.vue @@ -0,0 +1,55 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMediaImage.vue b/packages/frontend-embed/src/components/EmMediaImage.vue new file mode 100644 index 0000000000..d711020a74 --- /dev/null +++ b/packages/frontend-embed/src/components/EmMediaImage.vue @@ -0,0 +1,162 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMediaList.vue b/packages/frontend-embed/src/components/EmMediaList.vue new file mode 100644 index 0000000000..0b2d835abe --- /dev/null +++ b/packages/frontend-embed/src/components/EmMediaList.vue @@ -0,0 +1,146 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMediaVideo.vue b/packages/frontend-embed/src/components/EmMediaVideo.vue new file mode 100644 index 0000000000..e2779bdee4 --- /dev/null +++ b/packages/frontend-embed/src/components/EmMediaVideo.vue @@ -0,0 +1,64 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMention.vue b/packages/frontend-embed/src/components/EmMention.vue new file mode 100644 index 0000000000..a71364237d --- /dev/null +++ b/packages/frontend-embed/src/components/EmMention.vue @@ -0,0 +1,46 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmMfm.ts b/packages/frontend-embed/src/components/EmMfm.ts new file mode 100644 index 0000000000..cae2feb8fb --- /dev/null +++ b/packages/frontend-embed/src/components/EmMfm.ts @@ -0,0 +1,454 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { VNode, h, SetupContext, provide } from 'vue'; +import * as mfm from 'mfm-js'; +import * as Misskey from 'misskey-js'; +import { host } from '@@/js/config.js'; +import EmUrl from '@/components/EmUrl.vue'; +import EmTime from '@/components/EmTime.vue'; +import EmLink from '@/components/EmLink.vue'; +import EmMention from '@/components/EmMention.vue'; +import EmEmoji from '@/components/EmEmoji.vue'; +import EmCustomEmoji from '@/components/EmCustomEmoji.vue'; +import EmA from '@/components/EmA.vue'; + +function safeParseFloat(str: unknown): number | null { + if (typeof str !== 'string' || str === '') return null; + const num = parseFloat(str); + if (isNaN(num)) return null; + return num; +} + +const QUOTE_STYLE = ` +display: block; +margin: 8px; +padding: 6px 0 6px 12px; +color: var(--MI_THEME-fg); +border-left: solid 3px var(--MI_THEME-fg); +opacity: 0.7; +`.split('\n').join(' '); + +type MfmProps = { + text: string; + plain?: boolean; + nowrap?: boolean; + author?: Misskey.entities.UserLite; + isNote?: boolean; + emojiUrls?: Record; + rootScale?: number; + nyaize?: boolean | 'respect'; + parsedNodes?: mfm.MfmNode[] | null; +}; + +type MfmEvents = { + clickEv(id: string): void; +}; + +// eslint-disable-next-line import/no-default-export +export default function (props: MfmProps, { emit }: { emit: SetupContext['emit'] }) { + const isNote = props.isNote ?? true; + const shouldNyaize = props.nyaize ? props.nyaize === 'respect' ? props.author?.isCat : false : false; + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (props.text == null || props.text === '') return; + + const rootAst = props.parsedNodes ?? (props.plain ? mfm.parseSimple : mfm.parse)(props.text); + + const validTime = (t: string | boolean | null | undefined) => { + if (t == null) return null; + if (typeof t === 'boolean') return null; + return t.match(/^\-?[0-9.]+s$/) ? t : null; + }; + + const validColor = (c: unknown): string | null => { + if (typeof c !== 'string') return null; + return c.match(/^[0-9a-f]{3,6}$/i) ? c : null; + }; + + const useAnim = true; + + /** + * Gen Vue Elements from MFM AST + * @param ast MFM AST + * @param scale How times large the text is + * @param disableNyaize Whether nyaize is disabled or not + */ + const genEl = (ast: mfm.MfmNode[], scale: number, disableNyaize = false) => ast.map((token): VNode | string | (VNode | string)[] => { + switch (token.type) { + case 'text': { + let text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n'); + if (!disableNyaize && shouldNyaize) { + text = Misskey.nyaize(text); + } + + if (!props.plain) { + const res: (VNode | string)[] = []; + for (const t of text.split('\n')) { + res.push(h('br')); + res.push(t); + } + res.shift(); + return res; + } else { + return [text.replace(/\n/g, ' ')]; + } + } + + case 'bold': { + return [h('b', genEl(token.children, scale))]; + } + + case 'strike': { + return [h('del', genEl(token.children, scale))]; + } + + case 'italic': { + return h('i', { + style: 'font-style: oblique;', + }, genEl(token.children, scale)); + } + + case 'fn': { + // TODO: CSSを文字列で組み立てていくと token.props.args.~~~ 経由でCSSインジェクションできるのでよしなにやる + let style: string | undefined; + switch (token.props.name) { + case 'tada': { + const speed = validTime(token.props.args.speed) ?? '1s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = 'font-size: 150%;' + (useAnim ? `animation: global-tada ${speed} linear infinite both; animation-delay: ${delay};` : ''); + break; + } + case 'jelly': { + const speed = validTime(token.props.args.speed) ?? '1s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = (useAnim ? `animation: mfm-rubberBand ${speed} linear infinite both; animation-delay: ${delay};` : ''); + break; + } + case 'twitch': { + const speed = validTime(token.props.args.speed) ?? '0.5s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = useAnim ? `animation: mfm-twitch ${speed} ease infinite; animation-delay: ${delay};` : ''; + break; + } + case 'shake': { + const speed = validTime(token.props.args.speed) ?? '0.5s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = useAnim ? `animation: mfm-shake ${speed} ease infinite; animation-delay: ${delay};` : ''; + break; + } + case 'spin': { + const direction = + token.props.args.left ? 'reverse' : + token.props.args.alternate ? 'alternate' : + 'normal'; + const anime = + token.props.args.x ? 'mfm-spinX' : + token.props.args.y ? 'mfm-spinY' : + 'mfm-spin'; + const speed = validTime(token.props.args.speed) ?? '1.5s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = useAnim ? `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction}; animation-delay: ${delay};` : ''; + break; + } + case 'jump': { + const speed = validTime(token.props.args.speed) ?? '0.75s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = useAnim ? `animation: mfm-jump ${speed} linear infinite; animation-delay: ${delay};` : ''; + break; + } + case 'bounce': { + const speed = validTime(token.props.args.speed) ?? '0.75s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = useAnim ? `animation: mfm-bounce ${speed} linear infinite; transform-origin: center bottom; animation-delay: ${delay};` : ''; + break; + } + case 'flip': { + const transform = + (token.props.args.h && token.props.args.v) ? 'scale(-1, -1)' : + token.props.args.v ? 'scaleY(-1)' : + 'scaleX(-1)'; + style = `transform: ${transform};`; + break; + } + case 'x2': { + return h('span', { + class: 'mfm-x2', + }, genEl(token.children, scale * 2)); + } + case 'x3': { + return h('span', { + class: 'mfm-x3', + }, genEl(token.children, scale * 3)); + } + case 'x4': { + return h('span', { + class: 'mfm-x4', + }, genEl(token.children, scale * 4)); + } + case 'font': { + const family = + token.props.args.serif ? 'serif' : + token.props.args.monospace ? 'monospace' : + token.props.args.cursive ? 'cursive' : + token.props.args.fantasy ? 'fantasy' : + token.props.args.emoji ? 'emoji' : + token.props.args.math ? 'math' : + null; + if (family) style = `font-family: ${family};`; + break; + } + case 'blur': { + return h('span', { + class: '_mfm_blur_', + }, genEl(token.children, scale)); + } + case 'rainbow': { + if (!useAnim) { + return h('span', { + class: '_mfm_rainbow_fallback_', + }, genEl(token.children, scale)); + } + const speed = validTime(token.props.args.speed) ?? '1s'; + const delay = validTime(token.props.args.delay) ?? '0s'; + style = `animation: mfm-rainbow ${speed} linear infinite; animation-delay: ${delay};`; + break; + } + case 'sparkle': { + return genEl(token.children, scale); + } + case 'rotate': { + const degrees = safeParseFloat(token.props.args.deg) ?? 90; + style = `transform: rotate(${degrees}deg); transform-origin: center center;`; + break; + } + case 'position': { + const x = safeParseFloat(token.props.args.x) ?? 0; + const y = safeParseFloat(token.props.args.y) ?? 0; + style = `transform: translateX(${x}em) translateY(${y}em);`; + break; + } + case 'scale': { + const x = Math.min(safeParseFloat(token.props.args.x) ?? 1, 5); + const y = Math.min(safeParseFloat(token.props.args.y) ?? 1, 5); + style = `transform: scale(${x}, ${y});`; + scale = scale * Math.max(x, y); + break; + } + case 'fg': { + let color = validColor(token.props.args.color); + color = color ?? 'f00'; + style = `color: #${color}; overflow-wrap: anywhere;`; + break; + } + case 'bg': { + let color = validColor(token.props.args.color); + color = color ?? 'f00'; + style = `background-color: #${color}; overflow-wrap: anywhere;`; + break; + } + case 'border': { + let color = validColor(token.props.args.color); + color = color ? `#${color}` : 'var(--MI_THEME-accent)'; + let b_style = token.props.args.style; + if ( + typeof b_style !== 'string' || + !['hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'] + .includes(b_style) + ) b_style = 'solid'; + const width = safeParseFloat(token.props.args.width) ?? 1; + const radius = safeParseFloat(token.props.args.radius) ?? 0; + style = `border: ${width}px ${b_style} ${color}; border-radius: ${radius}px;${token.props.args.noclip ? '' : ' overflow: clip;'}`; + break; + } + case 'ruby': { + if (token.children.length === 1) { + const child = token.children[0]; + let text = child.type === 'text' ? child.props.text : ''; + if (!disableNyaize && shouldNyaize) { + text = Misskey.nyaize(text); + } + return h('ruby', {}, [text.split(' ')[0], h('rt', text.split(' ')[1])]); + } else { + const rt = token.children.at(-1)!; + let text = rt.type === 'text' ? rt.props.text : ''; + if (!disableNyaize && shouldNyaize) { + text = Misskey.nyaize(text); + } + return h('ruby', {}, [...genEl(token.children.slice(0, token.children.length - 1), scale), h('rt', text.trim())]); + } + } + case 'unixtime': { + const child = token.children[0]; + const unixtime = parseInt(child.type === 'text' ? child.props.text : ''); + return h('span', { + style: 'display: inline-block; font-size: 90%; border: solid 1px var(--MI_THEME-divider); border-radius: 999px; padding: 4px 10px 4px 6px;', + }, [ + h('i', { + class: 'ti ti-clock', + style: 'margin-right: 0.25em;', + }), + h(EmTime, { + key: Math.random(), + time: unixtime * 1000, + mode: 'detail', + }), + ]); + } + case 'clickable': { + return h('span', { onClick(ev: MouseEvent): void { + ev.stopPropagation(); + ev.preventDefault(); + const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : ''; + emit('clickEv', clickEv); + } }, genEl(token.children, scale)); + } + } + if (style === undefined) { + return h('span', {}, ['$[', token.props.name, ' ', ...genEl(token.children, scale), ']']); + } else { + return h('span', { + style: 'display: inline-block; ' + style, + }, genEl(token.children, scale)); + } + } + + case 'small': { + return [h('small', { + style: 'opacity: 0.7;', + }, genEl(token.children, scale))]; + } + + case 'center': { + return [h('div', { + style: 'text-align:center;', + }, genEl(token.children, scale))]; + } + + case 'url': { + return [h(EmUrl, { + key: Math.random(), + url: token.props.url, + rel: 'nofollow noopener', + })]; + } + + case 'link': { + return [h(EmLink, { + key: Math.random(), + url: token.props.url, + rel: 'nofollow noopener', + }, genEl(token.children, scale, true))]; + } + + case 'mention': { + return [h(EmMention, { + key: Math.random(), + host: (token.props.host == null && props.author && props.author.host != null ? props.author.host : token.props.host) ?? host, + username: token.props.username, + })]; + } + + case 'hashtag': { + return [h(EmA, { + key: Math.random(), + to: isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/user-tags/${encodeURIComponent(token.props.hashtag)}`, + style: 'color:var(--MI_THEME-hashtag);', + }, `#${token.props.hashtag}`)]; + } + + case 'blockCode': { + return [h('code', { + key: Math.random(), + lang: token.props.lang ?? undefined, + }, token.props.code)]; + } + + case 'inlineCode': { + return [h('code', { + key: Math.random(), + }, token.props.code)]; + } + + case 'quote': { + if (!props.nowrap) { + return [h('div', { + style: QUOTE_STYLE, + }, genEl(token.children, scale, true))]; + } else { + return [h('span', { + style: QUOTE_STYLE, + }, genEl(token.children, scale, true))]; + } + } + + case 'emojiCode': { + if (props.author?.host == null) { + return [h(EmCustomEmoji, { + key: Math.random(), + name: token.props.name, + normal: props.plain, + host: null, + useOriginalSize: scale >= 2.5, + fallbackToImage: false, + })]; + } else { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (props.emojiUrls && (props.emojiUrls[token.props.name] == null)) { + return [h('span', `:${token.props.name}:`)]; + } else { + return [h(EmCustomEmoji, { + key: Math.random(), + name: token.props.name, + url: props.emojiUrls && props.emojiUrls[token.props.name], + normal: props.plain, + host: props.author.host, + useOriginalSize: scale >= 2.5, + })]; + } + } + } + + case 'unicodeEmoji': { + return [h(EmEmoji, { + key: Math.random(), + emoji: token.props.emoji, + menu: props.enableEmojiMenu, + menuReaction: props.enableEmojiMenuReaction, + })]; + } + + case 'mathInline': { + return [h('code', token.props.formula)]; + } + + case 'mathBlock': { + return [h('code', token.props.formula)]; + } + + case 'search': { + return [h('div', { + key: Math.random(), + }, token.props.query)]; + } + + case 'plain': { + return [h('span', genEl(token.children, scale, true))]; + } + + default: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + console.error('unrecognized ast type:', (token as any).type); + + return []; + } + } + }).flat(Infinity) as (VNode | string)[]; + + return h('span', { + // https://codeday.me/jp/qa/20190424/690106.html + style: props.nowrap ? 'white-space: pre; word-wrap: normal; overflow: hidden; text-overflow: ellipsis;' : 'white-space: pre-wrap;', + }, genEl(rootAst, props.rootScale ?? 1)); +} diff --git a/packages/frontend-embed/src/components/EmNote.vue b/packages/frontend-embed/src/components/EmNote.vue new file mode 100644 index 0000000000..d4b4827c90 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNote.vue @@ -0,0 +1,611 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmNoteDetailed.vue b/packages/frontend-embed/src/components/EmNoteDetailed.vue new file mode 100644 index 0000000000..b39b47c065 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNoteDetailed.vue @@ -0,0 +1,490 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmNoteHeader.vue b/packages/frontend-embed/src/components/EmNoteHeader.vue new file mode 100644 index 0000000000..85b4aac071 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNoteHeader.vue @@ -0,0 +1,104 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmNoteSimple.vue b/packages/frontend-embed/src/components/EmNoteSimple.vue new file mode 100644 index 0000000000..b9aaf3fa4a --- /dev/null +++ b/packages/frontend-embed/src/components/EmNoteSimple.vue @@ -0,0 +1,106 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmNoteSub.vue b/packages/frontend-embed/src/components/EmNoteSub.vue new file mode 100644 index 0000000000..59be8608e0 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNoteSub.vue @@ -0,0 +1,151 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmNotes.vue b/packages/frontend-embed/src/components/EmNotes.vue new file mode 100644 index 0000000000..4211261e19 --- /dev/null +++ b/packages/frontend-embed/src/components/EmNotes.vue @@ -0,0 +1,52 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmPagination.vue b/packages/frontend-embed/src/components/EmPagination.vue new file mode 100644 index 0000000000..5d5317a912 --- /dev/null +++ b/packages/frontend-embed/src/components/EmPagination.vue @@ -0,0 +1,504 @@ + + + + + + + + diff --git a/packages/frontend-embed/src/components/EmPoll.vue b/packages/frontend-embed/src/components/EmPoll.vue new file mode 100644 index 0000000000..d197e094c6 --- /dev/null +++ b/packages/frontend-embed/src/components/EmPoll.vue @@ -0,0 +1,82 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmReactionIcon.vue b/packages/frontend-embed/src/components/EmReactionIcon.vue new file mode 100644 index 0000000000..5c38ecb0ed --- /dev/null +++ b/packages/frontend-embed/src/components/EmReactionIcon.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/frontend-embed/src/components/EmReactionsViewer.reaction.vue b/packages/frontend-embed/src/components/EmReactionsViewer.reaction.vue new file mode 100644 index 0000000000..2ebff489fd --- /dev/null +++ b/packages/frontend-embed/src/components/EmReactionsViewer.reaction.vue @@ -0,0 +1,99 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmReactionsViewer.vue b/packages/frontend-embed/src/components/EmReactionsViewer.vue new file mode 100644 index 0000000000..014dd1c935 --- /dev/null +++ b/packages/frontend-embed/src/components/EmReactionsViewer.vue @@ -0,0 +1,104 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmSubNoteContent.vue b/packages/frontend-embed/src/components/EmSubNoteContent.vue new file mode 100644 index 0000000000..61815ddfd8 --- /dev/null +++ b/packages/frontend-embed/src/components/EmSubNoteContent.vue @@ -0,0 +1,114 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmTime.vue b/packages/frontend-embed/src/components/EmTime.vue new file mode 100644 index 0000000000..7902e18483 --- /dev/null +++ b/packages/frontend-embed/src/components/EmTime.vue @@ -0,0 +1,107 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmTimelineContainer.vue b/packages/frontend-embed/src/components/EmTimelineContainer.vue new file mode 100644 index 0000000000..60fd67ced9 --- /dev/null +++ b/packages/frontend-embed/src/components/EmTimelineContainer.vue @@ -0,0 +1,39 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmUrl.vue b/packages/frontend-embed/src/components/EmUrl.vue new file mode 100644 index 0000000000..94424cab28 --- /dev/null +++ b/packages/frontend-embed/src/components/EmUrl.vue @@ -0,0 +1,96 @@ + + + + + + + diff --git a/packages/frontend-embed/src/components/EmUserName.vue b/packages/frontend-embed/src/components/EmUserName.vue new file mode 100644 index 0000000000..c0c7c443ca --- /dev/null +++ b/packages/frontend-embed/src/components/EmUserName.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/packages/frontend-embed/src/components/I18n.vue b/packages/frontend-embed/src/components/I18n.vue new file mode 100644 index 0000000000..b621110ec9 --- /dev/null +++ b/packages/frontend-embed/src/components/I18n.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/packages/frontend-embed/src/custom-emojis.ts b/packages/frontend-embed/src/custom-emojis.ts new file mode 100644 index 0000000000..d5b40885c1 --- /dev/null +++ b/packages/frontend-embed/src/custom-emojis.ts @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { shallowRef, watch } from 'vue'; +import * as Misskey from 'misskey-js'; +import { misskeyApi, misskeyApiGet } from '@/misskey-api.js'; + +function get(key: string) { + const value = localStorage.getItem(key); + if (value === null) return null; + return JSON.parse(value); +} + +function set(key: string, value: any) { + localStorage.setItem(key, JSON.stringify(value)); +} + +const storageCache = await get('emojis'); +export const customEmojis = shallowRef(Array.isArray(storageCache) ? storageCache : []); + +export const customEmojisMap = new Map(); +watch(customEmojis, emojis => { + customEmojisMap.clear(); + for (const emoji of emojis) { + customEmojisMap.set(emoji.name, emoji); + } +}, { immediate: true }); + +export async function fetchCustomEmojis(force = false) { + const now = Date.now(); + + let res; + if (force) { + res = await misskeyApi('emojis', {}); + } else { + const lastFetchedAt = await get('lastEmojisFetchedAt'); + if (lastFetchedAt && (now - lastFetchedAt) < 1000 * 60 * 60) return; + res = await misskeyApiGet('emojis', {}); + } + + customEmojis.value = res.emojis; + set('emojis', res.emojis); + set('lastEmojisFetchedAt', now); +} + +let cachedTags; +export function getCustomEmojiTags() { + if (cachedTags) return cachedTags; + + const tags = new Set(); + for (const emoji of customEmojis.value) { + for (const tag of emoji.aliases) { + tags.add(tag); + } + } + const res = Array.from(tags); + cachedTags = res; + return res; +} diff --git a/packages/frontend-embed/src/di.ts b/packages/frontend-embed/src/di.ts new file mode 100644 index 0000000000..22f6276630 --- /dev/null +++ b/packages/frontend-embed/src/di.ts @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type { InjectionKey } from 'vue'; +import * as Misskey from 'misskey-js'; +import { MediaProxy } from '@@/js/media-proxy.js'; +import type { ParsedEmbedParams } from '@@/js/embed-page.js'; +import type { ServerContext } from '@/server-context.js'; + +export const DI = { + serverMetadata: Symbol() as InjectionKey, + embedParams: Symbol() as InjectionKey, + serverContext: Symbol() as InjectionKey, + mediaProxy: Symbol() as InjectionKey, +}; diff --git a/packages/frontend-embed/src/i18n.ts b/packages/frontend-embed/src/i18n.ts new file mode 100644 index 0000000000..6ad503b089 --- /dev/null +++ b/packages/frontend-embed/src/i18n.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { markRaw } from 'vue'; +import { I18n } from '@@/js/i18n.js'; +import type { Locale } from '../../../locales/index.js'; +import { locale } from '@@/js/config.js'; + +export const i18n = markRaw(new I18n(locale, _DEV_)); + +export function updateI18n(newLocale: Locale) { + i18n.locale = newLocale; +} diff --git a/packages/frontend-embed/src/index.html b/packages/frontend-embed/src/index.html new file mode 100644 index 0000000000..47b0b0e84e --- /dev/null +++ b/packages/frontend-embed/src/index.html @@ -0,0 +1,36 @@ + + + + + + + + + [DEV] Loading... + + + + + + + +

+ + + diff --git a/packages/frontend-embed/src/misskey-api.ts b/packages/frontend-embed/src/misskey-api.ts new file mode 100644 index 0000000000..0d3c679359 --- /dev/null +++ b/packages/frontend-embed/src/misskey-api.ts @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Misskey from 'misskey-js'; +import { ref } from 'vue'; +import { apiUrl } from '@@/js/config.js'; + +export const pendingApiRequestsCount = ref(0); + +// Implements Misskey.api.ApiClient.request +export function misskeyApi< + ResT = void, + E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, + P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], + _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, +>( + endpoint: E, + data: P = {} as any, + signal?: AbortSignal, +): Promise<_ResT> { + if (endpoint.includes('://')) throw new Error('invalid endpoint'); + pendingApiRequestsCount.value++; + + const onFinally = () => { + pendingApiRequestsCount.value--; + }; + + const promise = new Promise<_ResT>((resolve, reject) => { + // Send request + window.fetch(`${apiUrl}/${endpoint}`, { + method: 'POST', + body: JSON.stringify(data), + credentials: 'omit', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + signal, + }).then(async (res) => { + const body = res.status === 204 ? null : await res.json(); + + if (res.status === 200) { + resolve(body); + } else if (res.status === 204) { + resolve(undefined as _ResT); // void -> undefined + } else { + reject(body.error); + } + }).catch(reject); + }); + + promise.then(onFinally, onFinally); + + return promise; +} + +// Implements Misskey.api.ApiClient.request +export function misskeyApiGet< + ResT = void, + E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, + P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], + _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, +>( + endpoint: E, + data: P = {} as any, +): Promise<_ResT> { + pendingApiRequestsCount.value++; + + const onFinally = () => { + pendingApiRequestsCount.value--; + }; + + const query = new URLSearchParams(data as any); + + const promise = new Promise<_ResT>((resolve, reject) => { + // Send request + window.fetch(`${apiUrl}/${endpoint}?${query}`, { + method: 'GET', + credentials: 'omit', + cache: 'default', + }).then(async (res) => { + const body = res.status === 204 ? null : await res.json(); + + if (res.status === 200) { + resolve(body); + } else if (res.status === 204) { + resolve(undefined as _ResT); // void -> undefined + } else { + reject(body.error); + } + }).catch(reject); + }); + + promise.then(onFinally, onFinally); + + return promise; +} diff --git a/packages/frontend-embed/src/pages/clip.vue b/packages/frontend-embed/src/pages/clip.vue new file mode 100644 index 0000000000..f4d4e8cf6f --- /dev/null +++ b/packages/frontend-embed/src/pages/clip.vue @@ -0,0 +1,143 @@ + + + + + + + diff --git a/packages/frontend-embed/src/pages/not-found.vue b/packages/frontend-embed/src/pages/not-found.vue new file mode 100644 index 0000000000..bbb03b4e64 --- /dev/null +++ b/packages/frontend-embed/src/pages/not-found.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/frontend-embed/src/pages/note.vue b/packages/frontend-embed/src/pages/note.vue new file mode 100644 index 0000000000..e879430286 --- /dev/null +++ b/packages/frontend-embed/src/pages/note.vue @@ -0,0 +1,52 @@ + + + + + + + diff --git a/packages/frontend-embed/src/pages/tag.vue b/packages/frontend-embed/src/pages/tag.vue new file mode 100644 index 0000000000..4b00ae7c2d --- /dev/null +++ b/packages/frontend-embed/src/pages/tag.vue @@ -0,0 +1,126 @@ + + + + + + + diff --git a/packages/frontend-embed/src/pages/user-timeline.vue b/packages/frontend-embed/src/pages/user-timeline.vue new file mode 100644 index 0000000000..348b1a7622 --- /dev/null +++ b/packages/frontend-embed/src/pages/user-timeline.vue @@ -0,0 +1,158 @@ + + + + + + + diff --git a/packages/frontend-embed/src/post-message.ts b/packages/frontend-embed/src/post-message.ts new file mode 100644 index 0000000000..fd8eb8a5d2 --- /dev/null +++ b/packages/frontend-embed/src/post-message.ts @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export const postMessageEventTypes = [ + 'misskey:embed:ready', + 'misskey:embed:changeHeight', +] as const; + +export type PostMessageEventType = typeof postMessageEventTypes[number]; + +export interface PostMessageEventPayload extends Record { + 'misskey:embed:ready': undefined; + 'misskey:embed:changeHeight': { + height: number; + }; +} + +export type MiPostMessageEvent = { + type: T; + iframeId?: string; + payload?: PostMessageEventPayload[T]; +} + +let defaultIframeId: string | null = null; + +export function setIframeId(id: string): void { + if (defaultIframeId != null) return; + + if (_DEV_) console.log('setIframeId', id); + defaultIframeId = id; +} + +/** + * 親フレームにイベントを送信 + */ +export function postMessageToParentWindow(type: T, payload?: PostMessageEventPayload[T], iframeId: string | null = null): void { + let _iframeId = iframeId; + if (_iframeId == null) { + _iframeId = defaultIframeId; + } + if (_DEV_) console.log('postMessageToParentWindow', type, _iframeId, payload); + window.parent.postMessage({ + type, + iframeId: _iframeId, + payload, + }, '*'); +} diff --git a/packages/frontend-embed/src/server-context.ts b/packages/frontend-embed/src/server-context.ts new file mode 100644 index 0000000000..a84a1a726a --- /dev/null +++ b/packages/frontend-embed/src/server-context.ts @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ +import * as Misskey from 'misskey-js'; + +const providedContextEl = document.getElementById('misskey_embedCtx'); + +export type ServerContext = { + clip?: Misskey.entities.Clip; + note?: Misskey.entities.Note; + user?: Misskey.entities.UserLite; +} | null; + +// NOTE: devモードのときしか embedCtx が null になることは無い +export const serverContext: ServerContext = (providedContextEl && providedContextEl.textContent) ? JSON.parse(providedContextEl.textContent) : null; + +export function assertServerContext>(ctx: ServerContext, entity: K): ctx is Required, K>> { + if (ctx == null) return false; + return entity in ctx; +} diff --git a/packages/frontend-embed/src/server-metadata.ts b/packages/frontend-embed/src/server-metadata.ts new file mode 100644 index 0000000000..6c94aacd48 --- /dev/null +++ b/packages/frontend-embed/src/server-metadata.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Misskey from 'misskey-js'; +import { misskeyApi } from '@/misskey-api.js'; + +const providedMetaEl = document.getElementById('misskey_meta'); + +const _serverMetadata: Misskey.entities.MetaDetailed | null = (providedMetaEl && providedMetaEl.textContent) ? JSON.parse(providedMetaEl.textContent) : null; + +// NOTE: devモードのときしか _serverMetadata が null になることは無い +export const serverMetadata: Misskey.entities.MetaDetailed = _serverMetadata ?? await misskeyApi('meta', { + detail: true, +}); diff --git a/packages/frontend-embed/src/style.scss b/packages/frontend-embed/src/style.scss new file mode 100644 index 0000000000..2e43cfd20a --- /dev/null +++ b/packages/frontend-embed/src/style.scss @@ -0,0 +1,453 @@ +@charset "utf-8"; + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +:root { + --MI-radius: 12px; + --MI-marginFull: 14px; + --MI-marginHalf: 10px; + + --MI-margin: var(--MI-marginFull); +} + +html { + background-color: transparent; + color-scheme: light dark; + color: var(--MI_THEME-fg); + accent-color: var(--MI_THEME-accent); + overflow: clip; + overflow-wrap: break-word; + font-family: 'Hiragino Maru Gothic Pro', "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif; + font-size: 14px; + line-height: 1.35; + text-size-adjust: 100%; + tab-size: 2; + -webkit-text-size-adjust: 100%; + + &, * { + scrollbar-color: var(--MI_THEME-scrollbarHandle) transparent; + scrollbar-width: thin; + + &::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + &::-webkit-scrollbar-track { + background: inherit; + } + + &::-webkit-scrollbar-thumb { + background: var(--MI_THEME-scrollbarHandle); + + &:hover { + background: var(--MI_THEME-scrollbarHandleHover); + } + + &:active { + background: var(--MI_THEME-accent); + } + } + } +} + +html, body { + height: 100%; + touch-action: manipulation; + margin: 0; + padding: 0; + scroll-behavior: smooth; +} + +#misskey_app { + height: 100%; +} + +a { + text-decoration: none; + cursor: pointer; + color: inherit; + tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; + + &:focus-visible { + outline-offset: 2px; + } + + &:hover { + text-decoration: underline; + } + + &[target="_blank"] { + -webkit-touch-callout: default; + } +} + +rt { + white-space: initial; +} + +:focus-visible { + outline: var(--MI_THEME-focus) solid 2px; + outline-offset: -2px; + + &:hover { + text-decoration: none; + } +} + +.ti { + width: 1.28em; + vertical-align: -12%; + line-height: 1em; + + &::before { + font-size: 128%; + } +} + +.ti-fw { + display: inline-block; + text-align: center; +} + +._nowrap { + white-space: pre !important; + word-wrap: normal !important; // https://codeday.me/jp/qa/20190424/690106.html + overflow: hidden; + text-overflow: ellipsis; +} + +._button { + user-select: none; + -webkit-user-select: none; + -webkit-touch-callout: none; + appearance: none; + display: inline-block; + padding: 0; + margin: 0; // for Safari + background: none; + border: none; + cursor: pointer; + color: inherit; + touch-action: manipulation; + tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; + font-size: 1em; + font-family: inherit; + line-height: inherit; + max-width: 100%; + + &:disabled { + opacity: 0.5; + cursor: default; + } +} + +._buttonGray { + @extend ._button; + background: var(--MI_THEME-buttonBg); + + &:not(:disabled):hover { + background: var(--MI_THEME-buttonHoverBg); + } +} + +._buttonPrimary { + @extend ._button; + color: var(--MI_THEME-fgOnAccent); + background: var(--MI_THEME-accent); + + &:not(:disabled):hover { + background: hsl(from var(--MI_THEME-accent) h s calc(l + 5)); + } + + &:not(:disabled):active { + background: hsl(from var(--MI_THEME-accent) h s calc(l - 5)); + } +} + +._buttonGradate { + @extend ._buttonPrimary; + color: var(--MI_THEME-fgOnAccent); + background: linear-gradient(90deg, var(--MI_THEME-buttonGradateA), var(--MI_THEME-buttonGradateB)); + + &:not(:disabled):hover { + background: linear-gradient(90deg, hsl(from var(--MI_THEME-accent) h s calc(l + 5)), hsl(from var(--MI_THEME-accent) h s calc(l + 5))); + } + + &:not(:disabled):active { + background: linear-gradient(90deg, hsl(from var(--MI_THEME-accent) h s calc(l + 5)), hsl(from var(--MI_THEME-accent) h s calc(l + 5))); + } +} + +._buttonRounded { + font-size: 0.95em; + padding: 0.5em 1em; + min-width: 100px; + border-radius: 99rem; + + &._buttonPrimary, + &._buttonGradate { + font-weight: 700; + } +} + +._help { + color: var(--MI_THEME-accent); + cursor: help; +} + +._textButton { + @extend ._button; + color: var(--MI_THEME-accent); + + &:focus-visible { + outline-offset: 2px; + } + + &:not(:disabled):hover { + text-decoration: underline; + } +} + +._panel { + background: var(--MI_THEME-panel); + border-radius: var(--MI-radius); + overflow: clip; +} + +._margin { + margin: var(--MI-margin) 0; +} + +._gaps_m { + display: flex; + flex-direction: column; + gap: 1.5em; +} + +._gaps_s { + display: flex; + flex-direction: column; + gap: 0.75em; +} + +._gaps { + display: flex; + flex-direction: column; + gap: var(--MI-margin); +} + +._buttons { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +._buttonsCenter { + @extend ._buttons; + + justify-content: center; +} + +._borderButton { + @extend ._button; + display: block; + width: 100%; + padding: 10px; + box-sizing: border-box; + text-align: center; + border: solid 0.5px var(--MI_THEME-divider); + border-radius: var(--MI-radius); + + &:active { + border-color: var(--MI_THEME-accent); + } +} + +._popup { + background: var(--MI_THEME-popup); + border-radius: var(--MI-radius); + contain: content; +} + +._acrylic { + background: var(--MI_THEME-acrylicPanel); + -webkit-backdrop-filter: var(--MI-blur, blur(15px)); + backdrop-filter: var(--MI-blur, blur(15px)); +} + +._fullinfo { + padding: 64px 32px; + text-align: center; + + > img { + vertical-align: bottom; + height: 128px; + margin-bottom: 16px; + border-radius: 16px; + } +} + +._link { + color: var(--MI_THEME-link); +} + +._caption { + font-size: 0.8em; + opacity: 0.7; +} + +._monospace { + font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace !important; +} + +// MFM ----------------------------- + +._mfm_blur_ { + filter: blur(6px); + transition: filter 0.3s; + + &:hover { + filter: blur(0px); + } +} + +.mfm-x2 { + --mfm-zoom-size: 200%; +} + +.mfm-x3 { + --mfm-zoom-size: 400%; +} + +.mfm-x4 { + --mfm-zoom-size: 600%; +} + +.mfm-x2, .mfm-x3, .mfm-x4 { + font-size: var(--mfm-zoom-size); + + .mfm-x2, .mfm-x3, .mfm-x4 { + /* only half effective */ + font-size: calc(var(--mfm-zoom-size) / 2 + 50%); + + .mfm-x2, .mfm-x3, .mfm-x4 { + /* disabled */ + font-size: 100%; + } + } +} + +._mfm_rainbow_fallback_ { + background-image: linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(255, 165, 0) 17%, rgb(255, 255, 0) 33%, rgb(0, 255, 0) 50%, rgb(0, 255, 255) 67%, rgb(0, 0, 255) 83%, rgb(255, 0, 255) 100%); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +@keyframes mfm-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes mfm-spinX { + 0% { transform: perspective(128px) rotateX(0deg); } + 100% { transform: perspective(128px) rotateX(360deg); } +} + +@keyframes mfm-spinY { + 0% { transform: perspective(128px) rotateY(0deg); } + 100% { transform: perspective(128px) rotateY(360deg); } +} + +@keyframes mfm-jump { + 0% { transform: translateY(0); } + 25% { transform: translateY(-16px); } + 50% { transform: translateY(0); } + 75% { transform: translateY(-8px); } + 100% { transform: translateY(0); } +} + +@keyframes mfm-bounce { + 0% { transform: translateY(0) scale(1, 1); } + 25% { transform: translateY(-16px) scale(1, 1); } + 50% { transform: translateY(0) scale(1, 1); } + 75% { transform: translateY(0) scale(1.5, 0.75); } + 100% { transform: translateY(0) scale(1, 1); } +} + +// const val = () => `translate(${Math.floor(Math.random() * 20) - 10}px, ${Math.floor(Math.random() * 20) - 10}px)`; +// let css = ''; +// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; } +@keyframes mfm-twitch { + 0% { transform: translate(7px, -2px) } + 5% { transform: translate(-3px, 1px) } + 10% { transform: translate(-7px, -1px) } + 15% { transform: translate(0px, -1px) } + 20% { transform: translate(-8px, 6px) } + 25% { transform: translate(-4px, -3px) } + 30% { transform: translate(-4px, -6px) } + 35% { transform: translate(-8px, -8px) } + 40% { transform: translate(4px, 6px) } + 45% { transform: translate(-3px, 1px) } + 50% { transform: translate(2px, -10px) } + 55% { transform: translate(-7px, 0px) } + 60% { transform: translate(-2px, 4px) } + 65% { transform: translate(3px, -8px) } + 70% { transform: translate(6px, 7px) } + 75% { transform: translate(-7px, -2px) } + 80% { transform: translate(-7px, -8px) } + 85% { transform: translate(9px, 3px) } + 90% { transform: translate(-3px, -2px) } + 95% { transform: translate(-10px, 2px) } + 100% { transform: translate(-2px, -6px) } +} + +// const val = () => `translate(${Math.floor(Math.random() * 6) - 3}px, ${Math.floor(Math.random() * 6) - 3}px) rotate(${Math.floor(Math.random() * 24) - 12}deg)`; +// let css = ''; +// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; } +@keyframes mfm-shake { + 0% { transform: translate(-3px, -1px) rotate(-8deg) } + 5% { transform: translate(0px, -1px) rotate(-10deg) } + 10% { transform: translate(1px, -3px) rotate(0deg) } + 15% { transform: translate(1px, 1px) rotate(11deg) } + 20% { transform: translate(-2px, 1px) rotate(1deg) } + 25% { transform: translate(-1px, -2px) rotate(-2deg) } + 30% { transform: translate(-1px, 2px) rotate(-3deg) } + 35% { transform: translate(2px, 1px) rotate(6deg) } + 40% { transform: translate(-2px, -3px) rotate(-9deg) } + 45% { transform: translate(0px, -1px) rotate(-12deg) } + 50% { transform: translate(1px, 2px) rotate(10deg) } + 55% { transform: translate(0px, -3px) rotate(8deg) } + 60% { transform: translate(1px, -1px) rotate(8deg) } + 65% { transform: translate(0px, -1px) rotate(-7deg) } + 70% { transform: translate(-1px, -3px) rotate(6deg) } + 75% { transform: translate(0px, -2px) rotate(4deg) } + 80% { transform: translate(-2px, -1px) rotate(3deg) } + 85% { transform: translate(1px, -3px) rotate(-10deg) } + 90% { transform: translate(1px, 0px) rotate(3deg) } + 95% { transform: translate(-2px, 0px) rotate(-3deg) } + 100% { transform: translate(2px, 1px) rotate(2deg) } +} + +@keyframes mfm-rubberBand { + from { transform: scale3d(1, 1, 1); } + 30% { transform: scale3d(1.25, 0.75, 1); } + 40% { transform: scale3d(0.75, 1.25, 1); } + 50% { transform: scale3d(1.15, 0.85, 1); } + 65% { transform: scale3d(0.95, 1.05, 1); } + 75% { transform: scale3d(1.05, 0.95, 1); } + to { transform: scale3d(1, 1, 1); } +} + +@keyframes mfm-rainbow { + 0% { filter: hue-rotate(0deg) contrast(150%) saturate(150%); } + 100% { filter: hue-rotate(360deg) contrast(150%) saturate(150%); } +} diff --git a/packages/frontend-embed/src/theme.ts b/packages/frontend-embed/src/theme.ts new file mode 100644 index 0000000000..4664ad4880 --- /dev/null +++ b/packages/frontend-embed/src/theme.ts @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import tinycolor from 'tinycolor2'; +import lightTheme from '@@/themes/_light.json5'; +import darkTheme from '@@/themes/_dark.json5'; +import type { BundledTheme } from 'shiki/themes'; + +export type Theme = { + id: string; + name: string; + author: string; + desc?: string; + base?: 'dark' | 'light'; + props: Record; + codeHighlighter?: { + base: BundledTheme; + overrides?: Record; + } | { + base: '_none_'; + overrides: Record; + }; +}; + +let timeout: number | null = null; + +export function assertIsTheme(theme: Record): theme is Theme { + return typeof theme === 'object' && theme !== null && 'id' in theme && 'name' in theme && 'author' in theme && 'props' in theme; +} + +export function applyTheme(theme: Theme, persist = true) { + if (timeout) window.clearTimeout(timeout); + + document.documentElement.classList.add('_themeChanging_'); + + timeout = window.setTimeout(() => { + document.documentElement.classList.remove('_themeChanging_'); + }, 1000); + + const colorScheme = theme.base === 'dark' ? 'dark' : 'light'; + + document.documentElement.dataset.colorScheme = colorScheme; + + // Deep copy + const _theme = JSON.parse(JSON.stringify(theme)); + + if (_theme.base) { + const base = [lightTheme, darkTheme].find(x => x.id === _theme.base); + if (base) _theme.props = Object.assign({}, base.props, _theme.props); + } + + const props = compile(_theme); + + for (const tag of document.head.children) { + if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') { + tag.setAttribute('content', props['htmlThemeColor']); + break; + } + } + + for (const [k, v] of Object.entries(props)) { + document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString()); + } + + // iframeを正常に透過させるために、cssのcolor-schemeは `light dark;` 固定にしてある。style.scss参照 +} + +function compile(theme: Theme): Record { + function getColor(val: string): tinycolor.Instance { + if (val[0] === '@') { // ref (prop) + return getColor(theme.props[val.substring(1)]); + } else if (val[0] === '$') { // ref (const) + return getColor(theme.props[val]); + } else if (val[0] === ':') { // func + const parts = val.split('<'); + const func = parts.shift().substring(1); + const arg = parseFloat(parts.shift()); + const color = getColor(parts.join('<')); + + switch (func) { + case 'darken': return color.darken(arg); + case 'lighten': return color.lighten(arg); + case 'alpha': return color.setAlpha(arg); + case 'hue': return color.spin(arg); + case 'saturate': return color.saturate(arg); + } + } + + // other case + return tinycolor(val); + } + + const props = {}; + + for (const [k, v] of Object.entries(theme.props)) { + if (k.startsWith('$')) continue; // ignore const + + props[k] = v.startsWith('"') ? v.replace(/^"\s*/, '') : genValue(getColor(v)); + } + + return props; +} + +function genValue(c: tinycolor.Instance): string { + return c.toRgbString(); +} diff --git a/packages/frontend-embed/src/ui.vue b/packages/frontend-embed/src/ui.vue new file mode 100644 index 0000000000..4ba5968a91 --- /dev/null +++ b/packages/frontend-embed/src/ui.vue @@ -0,0 +1,110 @@ + + + + + + + diff --git a/packages/frontend-embed/src/utils.ts b/packages/frontend-embed/src/utils.ts new file mode 100644 index 0000000000..939648aa38 --- /dev/null +++ b/packages/frontend-embed/src/utils.ts @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Misskey from 'misskey-js'; +import { url } from '@@/js/config.js'; + +export const acct = (user: Misskey.Acct) => { + return Misskey.acct.toString(user); +}; + +export const userName = (user: Misskey.entities.User) => { + return user.name || user.username; +}; + +export const userPage = (user: Misskey.Acct, path?: string, absolute = false) => { + return `${absolute ? url : ''}/@${acct(user)}${(path ? `/${path}` : '')}`; +}; + +export const notePage = (note: Misskey.entities.Note) => { + return `/notes/${note.id}`; +}; diff --git a/packages/frontend-embed/src/workers/draw-blurhash.ts b/packages/frontend-embed/src/workers/draw-blurhash.ts new file mode 100644 index 0000000000..22de6cd3a8 --- /dev/null +++ b/packages/frontend-embed/src/workers/draw-blurhash.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { render } from 'buraha'; + +const canvas = new OffscreenCanvas(64, 64); + +onmessage = (event) => { + // console.log(event.data); + if (!('id' in event.data && typeof event.data.id === 'string')) { + return; + } + if (!('hash' in event.data && typeof event.data.hash === 'string')) { + return; + } + + render(event.data.hash, canvas); + const bitmap = canvas.transferToImageBitmap(); + postMessage({ id: event.data.id, bitmap }); +}; diff --git a/packages/frontend-embed/src/workers/test-webgl2.ts b/packages/frontend-embed/src/workers/test-webgl2.ts new file mode 100644 index 0000000000..b203ebe666 --- /dev/null +++ b/packages/frontend-embed/src/workers/test-webgl2.ts @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +const canvas = globalThis.OffscreenCanvas && new OffscreenCanvas(1, 1); +// 環境によってはOffscreenCanvasが存在しないため +// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition +const gl = canvas?.getContext('webgl2'); +if (gl) { + postMessage({ result: true }); +} else { + postMessage({ result: false }); +} diff --git a/packages/frontend-embed/src/workers/tsconfig.json b/packages/frontend-embed/src/workers/tsconfig.json new file mode 100644 index 0000000000..8ee8930465 --- /dev/null +++ b/packages/frontend-embed/src/workers/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "lib": ["esnext", "webworker"], + } +} diff --git a/packages/frontend-embed/tsconfig.json b/packages/frontend-embed/tsconfig.json new file mode 100644 index 0000000000..3701343623 --- /dev/null +++ b/packages/frontend-embed/tsconfig.json @@ -0,0 +1,53 @@ +{ + "compilerOptions": { + "allowJs": true, + "noEmitOnError": false, + "noImplicitAny": false, + "noImplicitReturns": true, + "noUnusedParameters": false, + "noUnusedLocals": false, + "noFallthroughCasesInSwitch": true, + "declaration": false, + "sourceMap": false, + "target": "ES2022", + "module": "nodenext", + "moduleResolution": "nodenext", + "removeComments": false, + "noLib": false, + "strict": true, + "strictNullChecks": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "isolatedModules": true, + "useDefineForClassFields": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + "@@/*": ["../frontend-shared/*"] + }, + "typeRoots": [ + "./@types", + "./node_modules/@types", + "./node_modules/@vue-macros", + "./node_modules" + ], + "types": [ + "vite/client", + ], + "lib": [ + "esnext", + "dom", + "dom.iterable" + ], + "jsx": "preserve" + }, + "compileOnSave": false, + "include": [ + "./**/*.ts", + "./**/*.vue" + ], + "exclude": [ + ".storybook/**/*" + ] +} diff --git a/packages/frontend-embed/vite.config.local-dev.ts b/packages/frontend-embed/vite.config.local-dev.ts new file mode 100644 index 0000000000..bf2f478887 --- /dev/null +++ b/packages/frontend-embed/vite.config.local-dev.ts @@ -0,0 +1,96 @@ +import dns from 'dns'; +import { readFile } from 'node:fs/promises'; +import type { IncomingMessage } from 'node:http'; +import { defineConfig } from 'vite'; +import type { UserConfig } from 'vite'; +import * as yaml from 'js-yaml'; +import locales from '../../locales/index.js'; +import { getConfig } from './vite.config.js'; + +dns.setDefaultResultOrder('ipv4first'); + +const defaultConfig = getConfig(); + +const { port } = yaml.load(await readFile('../../.config/default.yml', 'utf-8')); + +const httpUrl = `http://localhost:${port}/`; +const websocketUrl = `ws://localhost:${port}/`; + +// activitypubリクエストはProxyを通し、それ以外はViteの開発サーバーを返す +function varyHandler(req: IncomingMessage) { + if (req.headers.accept?.includes('application/activity+json')) { + return null; + } + return '/index.html'; +} + +const devConfig: UserConfig = { + // 基本の設定は vite.config.js から引き継ぐ + ...defaultConfig, + root: 'src', + publicDir: '../assets', + base: '/embed', + server: { + host: 'localhost', + port: 5174, + proxy: { + '/api': { + changeOrigin: true, + target: httpUrl, + }, + '/assets': httpUrl, + '/static-assets': httpUrl, + '/client-assets': httpUrl, + '/files': httpUrl, + '/twemoji': httpUrl, + '/fluent-emoji': httpUrl, + '/sw.js': httpUrl, + '/streaming': { + target: websocketUrl, + ws: true, + }, + '/favicon.ico': httpUrl, + '/robots.txt': httpUrl, + '/embed.js': httpUrl, + '/identicon': { + target: httpUrl, + rewrite(path) { + return path.replace('@localhost:5173', ''); + }, + }, + '/url': httpUrl, + '/proxy': httpUrl, + '/_info_card_': httpUrl, + '/bios': httpUrl, + '/cli': httpUrl, + '/inbox': httpUrl, + '/emoji/': httpUrl, + '/notes': { + target: httpUrl, + bypass: varyHandler, + }, + '/users': { + target: httpUrl, + bypass: varyHandler, + }, + '/.well-known': { + target: httpUrl, + }, + }, + }, + build: { + ...defaultConfig.build, + rollupOptions: { + ...defaultConfig.build?.rollupOptions, + input: 'index.html', + }, + }, + + define: { + ...defaultConfig.define, + _LANGS_FULL_: JSON.stringify(Object.entries(locales)), + }, +}; + +export default defineConfig(({ command, mode }) => devConfig); + diff --git a/packages/frontend-embed/vite.config.ts b/packages/frontend-embed/vite.config.ts new file mode 100644 index 0000000000..2dbee488c5 --- /dev/null +++ b/packages/frontend-embed/vite.config.ts @@ -0,0 +1,161 @@ +import path from 'path'; +import pluginVue from '@vitejs/plugin-vue'; +import { type UserConfig, defineConfig } from 'vite'; + +import locales from '../../locales/index.js'; +import meta from '../../package.json'; +import packageInfo from './package.json' with { type: 'json' }; +import pluginJson5 from './vite.json5.js'; + +const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue']; + +/** + * Misskeyのフロントエンドにバンドルせず、CDNなどから別途読み込むリソースを記述する。 + * CDNを使わずにバンドルしたい場合、以下の配列から該当要素を削除orコメントアウトすればOK + */ +const externalPackages = [ + // shiki(コードブロックのシンタックスハイライトで使用中)はテーマ・言語の定義の容量が大きいため、それらはCDNから読み込む + { + name: 'shiki', + match: /^shiki\/(?(langs|themes))$/, + path(id: string, pattern: RegExp): string { + const match = pattern.exec(id)?.groups; + return match + ? `https://esm.sh/shiki@${packageInfo.dependencies.shiki}/${match['subPkg']}` + : id; + }, + }, +]; + +const hash = (str: string, seed = 0): number => { + let h1 = 0xdeadbeef ^ seed, + h2 = 0x41c6ce57 ^ seed; + for (let i = 0, ch; i < str.length; i++) { + ch = str.charCodeAt(i); + h1 = Math.imul(h1 ^ ch, 2654435761); + h2 = Math.imul(h2 ^ ch, 1597334677); + } + + h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); + h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); + + return 4294967296 * (2097151 & h2) + (h1 >>> 0); +}; + +const BASE62_DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + +function toBase62(n: number): string { + if (n === 0) { + return '0'; + } + let result = ''; + while (n > 0) { + result = BASE62_DIGITS[n % BASE62_DIGITS.length] + result; + n = Math.floor(n / BASE62_DIGITS.length); + } + + return result; +} + +export function getConfig(): UserConfig { + return { + base: '/embed_vite/', + + server: { + port: 5174, + }, + + plugins: [ + pluginVue(), + pluginJson5(), + ], + + resolve: { + extensions, + alias: { + '@/': __dirname + '/src/', + '@@/': __dirname + '/../frontend-shared/', + '/client-assets/': __dirname + '/assets/', + '/static-assets/': __dirname + '/../backend/assets/' + }, + }, + + css: { + modules: { + generateScopedName(name, filename, _css): string { + const id = (path.relative(__dirname, filename.split('?')[0]) + '-' + name).replace(/[\\\/\.\?&=]/g, '-').replace(/(src-|vue-)/g, ''); + if (process.env.NODE_ENV === 'production') { + return 'x' + toBase62(hash(id)).substring(0, 4); + } else { + return id; + } + }, + }, + preprocessorOptions: { + scss: { + api: 'modern-compiler', + }, + }, + }, + + define: { + _VERSION_: JSON.stringify(meta.version), + _LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]) => [k, v._lang_])), + _ENV_: JSON.stringify(process.env.NODE_ENV), + _DEV_: process.env.NODE_ENV !== 'production', + _PERF_PREFIX_: JSON.stringify('Misskey:'), + __VUE_OPTIONS_API__: false, + __VUE_PROD_DEVTOOLS__: false, + }, + + build: { + target: [ + 'chrome116', + 'firefox116', + 'safari16', + ], + manifest: 'manifest.json', + rollupOptions: { + input: { + app: './src/boot.ts', + }, + external: externalPackages.map(p => p.match), + output: { + manualChunks: { + vue: ['vue'], + }, + chunkFileNames: process.env.NODE_ENV === 'production' ? '[hash:8].js' : '[name]-[hash:8].js', + assetFileNames: process.env.NODE_ENV === 'production' ? '[hash:8][extname]' : '[name]-[hash:8][extname]', + paths(id) { + for (const p of externalPackages) { + if (p.match.test(id)) { + return p.path(id, p.match); + } + } + + return id; + }, + }, + }, + cssCodeSplit: true, + outDir: __dirname + '/../../built/_frontend_embed_vite_', + assetsDir: '.', + emptyOutDir: false, + sourcemap: process.env.NODE_ENV === 'development', + reportCompressedSize: false, + + // https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies + commonjsOptions: { + include: [/misskey-js/, /node_modules/], + }, + }, + + worker: { + format: 'es', + }, + }; +} + +const config = defineConfig(({ command, mode }) => getConfig()); + +export default config; diff --git a/packages/frontend-embed/vite.json5.ts b/packages/frontend-embed/vite.json5.ts new file mode 100644 index 0000000000..87b67c2142 --- /dev/null +++ b/packages/frontend-embed/vite.json5.ts @@ -0,0 +1,48 @@ +// Original: https://github.com/rollup/plugins/tree/8835dd2aed92f408d7dc72d7cc25a9728e16face/packages/json + +import JSON5 from 'json5'; +import { Plugin } from 'rollup'; +import { createFilter, dataToEsm } from '@rollup/pluginutils'; +import { RollupJsonOptions } from '@rollup/plugin-json'; + +// json5 extends SyntaxError with additional fields (without subclassing) +// https://github.com/json5/json5/blob/de344f0619bda1465a6e25c76f1c0c3dda8108d9/lib/parse.js#L1111-L1112 +interface Json5SyntaxError extends SyntaxError { + lineNumber: number; + columnNumber: number; +} + +export default function json5(options: RollupJsonOptions = {}): Plugin { + const filter = createFilter(options.include, options.exclude); + const indent = 'indent' in options ? options.indent : '\t'; + + return { + name: 'json5', + + // eslint-disable-next-line no-shadow + transform(json, id) { + if (id.slice(-6) !== '.json5' || !filter(id)) return null; + + try { + const parsed = JSON5.parse(json); + return { + code: dataToEsm(parsed, { + preferConst: options.preferConst, + compact: options.compact, + namedExports: options.namedExports, + indent, + }), + map: { mappings: '' }, + }; + } catch (err) { + if (!(err instanceof SyntaxError)) { + throw err; + } + const message = 'Could not parse JSON5 file'; + const { lineNumber, columnNumber } = err as Json5SyntaxError; + this.warn({ message, id, loc: { line: lineNumber, column: columnNumber } }); + return null; + } + }, + }; +} diff --git a/packages/frontend-embed/vue-shims.d.ts b/packages/frontend-embed/vue-shims.d.ts new file mode 100644 index 0000000000..eba994772d --- /dev/null +++ b/packages/frontend-embed/vue-shims.d.ts @@ -0,0 +1,6 @@ +/* eslint-disable */ +declare module "*.vue" { + import { defineComponent } from "vue"; + const component: ReturnType; + export default component; +} diff --git a/packages/frontend-shared/.gitignore b/packages/frontend-shared/.gitignore new file mode 100644 index 0000000000..5f6be09d7c --- /dev/null +++ b/packages/frontend-shared/.gitignore @@ -0,0 +1,2 @@ +/storybook-static +js-built diff --git a/packages/frontend-shared/@types/global.d.ts b/packages/frontend-shared/@types/global.d.ts new file mode 100644 index 0000000000..4b8d679e75 --- /dev/null +++ b/packages/frontend-shared/@types/global.d.ts @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type FIXME = any; + +declare const _LANGS_: string[][]; +declare const _VERSION_: string; +declare const _ENV_: string; +declare const _DEV_: boolean; +declare const _PERF_PREFIX_: string; +declare const _DATA_TRANSFER_DRIVE_FILE_: string; +declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; +declare const _DATA_TRANSFER_DECK_COLUMN_: string; + +// for dev-mode +declare const _LANGS_FULL_: string[][]; + +// TagCanvas +interface Window { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + TagCanvas: any; +} diff --git a/packages/frontend-shared/build.js b/packages/frontend-shared/build.js new file mode 100644 index 0000000000..17b6da8d30 --- /dev/null +++ b/packages/frontend-shared/build.js @@ -0,0 +1,106 @@ +import fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import * as esbuild from 'esbuild'; +import { build } from 'esbuild'; +import { globSync } from 'glob'; +import { execa } from 'execa'; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); +const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); + +const entryPoints = globSync('./js/**/**.{ts,tsx}'); + +/** @type {import('esbuild').BuildOptions} */ +const options = { + entryPoints, + minify: process.env.NODE_ENV === 'production', + outdir: './js-built', + target: 'es2022', + platform: 'browser', + format: 'esm', + sourcemap: 'linked', +}; + +// js-built配下をすべて削除する +fs.rmSync('./js-built', { recursive: true, force: true }); + +if (process.argv.map(arg => arg.toLowerCase()).includes('--watch')) { + await watchSrc(); +} else { + await buildSrc(); +} + +async function buildSrc() { + console.log(`[${_package.name}] start building...`); + + await build(options) + .then(() => { + console.log(`[${_package.name}] build succeeded.`); + }) + .catch((err) => { + process.stderr.write(err.stderr); + process.exit(1); + }); + + if (process.env.NODE_ENV === 'production') { + console.log(`[${_package.name}] skip building d.ts because NODE_ENV is production.`); + } else { + await buildDts(); + } + + fs.copyFileSync('./js/emojilist.json', './js-built/emojilist.json'); + + console.log(`[${_package.name}] finish building.`); +} + +function buildDts() { + return execa( + 'tsc', + [ + '--project', 'tsconfig.json', + '--outDir', 'js-built', + '--declaration', 'true', + '--emitDeclarationOnly', 'true', + ], + { + stdout: process.stdout, + stderr: process.stderr, + }, + ); +} + +async function watchSrc() { + const plugins = [{ + name: 'gen-dts', + setup(build) { + build.onStart(() => { + console.log(`[${_package.name}] detect changed...`); + }); + build.onEnd(async result => { + if (result.errors.length > 0) { + console.error(`[${_package.name}] watch build failed:`, result); + return; + } + await buildDts(); + }); + }, + }]; + + console.log(`[${_package.name}] start watching...`); + + const context = await esbuild.context({ ...options, plugins }); + await context.watch(); + + await new Promise((resolve, reject) => { + process.on('SIGHUP', resolve); + process.on('SIGINT', resolve); + process.on('SIGTERM', resolve); + process.on('uncaughtException', reject); + process.on('exit', resolve); + }).finally(async () => { + await context.dispose(); + console.log(`[${_package.name}] finish watching.`); + }); +} diff --git a/packages/frontend-shared/eslint.config.js b/packages/frontend-shared/eslint.config.js new file mode 100644 index 0000000000..cd4641a270 --- /dev/null +++ b/packages/frontend-shared/eslint.config.js @@ -0,0 +1,100 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import parser from 'vue-eslint-parser'; +import pluginVue from 'eslint-plugin-vue'; +import pluginMisskey from '@misskey-dev/eslint-plugin'; +import sharedConfig from '../shared/eslint.config.js'; + +// eslint-disable-next-line import/no-default-export +export default [ + ...sharedConfig, + { + files: ['**/*.vue'], + ...pluginMisskey.configs.typescript, + }, + ...pluginVue.configs['flat/recommended'], + { + files: [ + '@types/**/*.ts', + 'js/**/*.ts', + '**/*.vue', + ], + languageOptions: { + globals: { + ...Object.fromEntries(Object.entries(globals.node).map(([key]) => [key, 'off'])), + ...globals.browser, + + // Node.js + module: false, + require: false, + __dirname: false, + + // Misskey + _DEV_: false, + _LANGS_: false, + _VERSION_: false, + _ENV_: false, + _PERF_PREFIX_: false, + _DATA_TRANSFER_DRIVE_FILE_: false, + _DATA_TRANSFER_DRIVE_FOLDER_: false, + _DATA_TRANSFER_DECK_COLUMN_: false, + }, + parser, + parserOptions: { + extraFileExtensions: ['.vue'], + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-empty-interface': ['error', { + allowSingleExtends: true, + }], + // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため + // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため + 'id-denylist': ['error', 'window', 'e'], + 'no-shadow': ['warn'], + 'vue/attributes-order': ['error', { + alphabetical: false, + }], + 'vue/no-use-v-if-with-v-for': ['error', { + allowUsingIterationVar: false, + }], + 'vue/no-ref-as-operand': 'error', + 'vue/no-multi-spaces': ['error', { + ignoreProperties: false, + }], + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'error', + 'vue/html-indent': ['warn', 'tab', { + attribute: 1, + baseIndent: 0, + closeBracket: 0, + alignAttributesVertically: true, + ignores: [], + }], + 'vue/html-closing-bracket-spacing': ['warn', { + startTag: 'never', + endTag: 'never', + selfClosingTag: 'never', + }], + 'vue/multi-word-component-names': 'warn', + 'vue/require-v-for-key': 'warn', + 'vue/no-unused-components': 'warn', + 'vue/no-unused-vars': 'warn', + 'vue/no-dupe-keys': 'warn', + 'vue/valid-v-for': 'warn', + 'vue/return-in-computed-property': 'warn', + 'vue/no-setup-props-reactivity-loss': 'warn', + 'vue/max-attributes-per-line': 'off', + 'vue/html-self-closing': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/v-on-event-hyphenation': ['error', 'never', { + autofix: true, + }], + 'vue/attribute-hyphenation': ['error', 'never'], + }, + }, +]; diff --git a/packages/frontend/src/scripts/collapsed.ts b/packages/frontend-shared/js/collapsed.ts similarity index 86% rename from packages/frontend/src/scripts/collapsed.ts rename to packages/frontend-shared/js/collapsed.ts index 4ec88a3c65..af1f88cb73 100644 --- a/packages/frontend/src/scripts/collapsed.ts +++ b/packages/frontend-shared/js/collapsed.ts @@ -7,7 +7,7 @@ import * as Misskey from 'misskey-js'; export function shouldCollapsed(note: Misskey.entities.Note, urls: string[]): boolean { const collapsed = note.cw == null && ( - note.text != null && ( + (note.text != null && ( (note.text.includes('$[x2')) || (note.text.includes('$[x3')) || (note.text.includes('$[x4')) || @@ -15,7 +15,7 @@ export function shouldCollapsed(note: Misskey.entities.Note, urls: string[]): bo (note.text.split('\n').length > 9) || (note.text.length > 500) || (urls.length >= 4) - ) || note.files.length >= 5 + )) || (note.files != null && note.files.length >= 5) ); return collapsed; diff --git a/packages/frontend/src/config.ts b/packages/frontend-shared/js/config.ts similarity index 51% rename from packages/frontend/src/config.ts rename to packages/frontend-shared/js/config.ts index 277dfc12aa..ae1dcae10b 100644 --- a/packages/frontend/src/config.ts +++ b/packages/frontend-shared/js/config.ts @@ -3,8 +3,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { miLocalStorage } from '@/local-storage.js'; +import type { Locale } from '../../../locales/index.js'; +// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const address = new URL(document.querySelector('meta[property="instance_url"]')?.content || location.href); const siteName = document.querySelector('meta[property="og:site_name"]')?.content; @@ -13,15 +14,15 @@ export const hostname = address.hostname; export const url = address.origin; export const apiUrl = location.origin + '/api'; export const wsOrigin = location.origin; -export const lang = miLocalStorage.getItem('lang') ?? 'en-US'; +export const lang = localStorage.getItem('lang') ?? 'en-US'; export const langs = _LANGS_; -const preParseLocale = miLocalStorage.getItem('locale'); -export let locale = preParseLocale ? JSON.parse(preParseLocale) : null; +const preParseLocale = localStorage.getItem('locale'); +export let locale: Locale = preParseLocale ? JSON.parse(preParseLocale) : null; export const version = _VERSION_; -export const instanceName = siteName === 'Misskey' || siteName == null ? host : siteName; -export const ui = miLocalStorage.getItem('ui'); -export const debug = miLocalStorage.getItem('debug') === 'true'; +export const instanceName = (siteName === 'Misskey' || siteName == null) ? host : siteName; +export const ui = localStorage.getItem('ui'); +export const debug = localStorage.getItem('debug') === 'true'; -export function updateLocale(newLocale): void { +export function updateLocale(newLocale: Locale): void { locale = newLocale; } diff --git a/packages/frontend/src/const.ts b/packages/frontend-shared/js/const.ts similarity index 93% rename from packages/frontend/src/const.ts rename to packages/frontend-shared/js/const.ts index 9e41926a97..4fe5cbb205 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -67,6 +67,9 @@ export const notificationTypes = [ 'followRequestAccepted', 'roleAssigned', 'achievementEarned', + 'exportCompleted', + 'login', + 'test', 'app', ] as const; export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const; @@ -87,6 +90,7 @@ export const ROLE_POLICIES = [ 'canHideAds', 'driveCapacityMb', 'alwaysMarkNsfw', + 'canUpdateBioMedia', 'pinLimit', 'antennaLimit', 'wordMuteLimit', @@ -97,6 +101,11 @@ export const ROLE_POLICIES = [ 'userEachUserListsLimit', 'rateLimitFactor', 'avatarDecorationLimit', + 'canImportAntennas', + 'canImportBlocking', + 'canImportFollowing', + 'canImportMuting', + 'canImportUserLists', ] as const; // なんか動かない @@ -126,7 +135,7 @@ export const MFM_PARAMS: Record = { position: ['x=', 'y='], fg: ['color='], bg: ['color='], - border: ['width=', 'style=', 'color=', 'radius=', 'noclip'], + border: ['width=', 'style=', 'color=', 'radius=', 'noclip'], font: ['serif', 'monospace', 'cursive', 'fantasy', 'emoji', 'math'], blur: [], rainbow: ['speed=', 'delay='], diff --git a/packages/frontend-shared/js/embed-page.ts b/packages/frontend-shared/js/embed-page.ts new file mode 100644 index 0000000000..d5555a98c3 --- /dev/null +++ b/packages/frontend-shared/js/embed-page.ts @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +//#region Embed関連の定義 + +/** 埋め込みの対象となるエンティティ(/embed/xxx の xxx の部分と対応させる) */ +const embeddableEntities = [ + 'notes', + 'user-timeline', + 'clips', + 'tags', +] as const; + +/** 埋め込みの対象となるエンティティ */ +export type EmbeddableEntity = typeof embeddableEntities[number]; + +/** 内部でスクロールがあるページ */ +export const embedRouteWithScrollbar: EmbeddableEntity[] = [ + 'clips', + 'tags', + 'user-timeline', +]; + +/** 埋め込みコードのパラメータ */ +export type EmbedParams = { + maxHeight?: number; + colorMode?: 'light' | 'dark'; + rounded?: boolean; + border?: boolean; + autoload?: boolean; + header?: boolean; +}; + +/** 正規化されたパラメータ */ +export type ParsedEmbedParams = Required> & Pick; + +/** パラメータのデフォルトの値 */ +export const defaultEmbedParams = { + maxHeight: undefined, + colorMode: undefined, + rounded: true, + border: true, + autoload: false, + header: true, +} as const satisfies EmbedParams; + +//#endregion + +/** + * パラメータを正規化する(埋め込みページ初期化用) + * @param searchParams URLSearchParamsもしくはクエリ文字列 + * @returns 正規化されたパラメータ + */ +export function parseEmbedParams(searchParams: URLSearchParams | string): ParsedEmbedParams { + let _searchParams: URLSearchParams; + if (typeof searchParams === 'string') { + _searchParams = new URLSearchParams(searchParams); + } else if (searchParams instanceof URLSearchParams) { + _searchParams = searchParams; + } else { + throw new Error('searchParams must be URLSearchParams or string'); + } + + function convertBoolean(value: string | null): boolean | undefined { + if (value === 'true') { + return true; + } else if (value === 'false') { + return false; + } + return undefined; + } + + function convertNumber(value: string | null): number | undefined { + if (value != null && !isNaN(Number(value))) { + return Number(value); + } + return undefined; + } + + function convertColorMode(value: string | null): 'light' | 'dark' | undefined { + if (value != null && ['light', 'dark'].includes(value)) { + return value as 'light' | 'dark'; + } + return undefined; + } + + return { + maxHeight: convertNumber(_searchParams.get('maxHeight')) ?? defaultEmbedParams.maxHeight, + colorMode: convertColorMode(_searchParams.get('colorMode')) ?? defaultEmbedParams.colorMode, + rounded: convertBoolean(_searchParams.get('rounded')) ?? defaultEmbedParams.rounded, + border: convertBoolean(_searchParams.get('border')) ?? defaultEmbedParams.border, + autoload: convertBoolean(_searchParams.get('autoload')) ?? defaultEmbedParams.autoload, + header: convertBoolean(_searchParams.get('header')) ?? defaultEmbedParams.header, + }; +} diff --git a/packages/frontend/src/scripts/emoji-base.ts b/packages/frontend-shared/js/emoji-base.ts similarity index 87% rename from packages/frontend/src/scripts/emoji-base.ts rename to packages/frontend-shared/js/emoji-base.ts index a01540a3e4..5fbbc4ea84 100644 --- a/packages/frontend/src/scripts/emoji-base.ts +++ b/packages/frontend-shared/js/emoji-base.ts @@ -19,7 +19,7 @@ export function char2fluentEmojiFilePath(char: string): string { // Fluent Emojiは国旗非対応 https://github.com/microsoft/fluentui-emoji/issues/25 if (codes[0]?.startsWith('1f1')) return char2twemojiFilePath(char); if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f'); - codes = codes.filter(x => x && x.length); - const fileName = codes.map(x => x!.padStart(4, '0')).join('-'); + codes = codes.filter(x => x != null && x.length > 0); + const fileName = (codes as string[]).map(x => x.padStart(4, '0')).join('-'); return `${fluentEmojiPngBase}/${fileName}.png`; } diff --git a/packages/frontend/src/emojilist.json b/packages/frontend-shared/js/emojilist.json similarity index 100% rename from packages/frontend/src/emojilist.json rename to packages/frontend-shared/js/emojilist.json diff --git a/packages/frontend/src/scripts/emojilist.ts b/packages/frontend-shared/js/emojilist.ts similarity index 96% rename from packages/frontend/src/scripts/emojilist.ts rename to packages/frontend-shared/js/emojilist.ts index 6565feba97..bde30a864f 100644 --- a/packages/frontend/src/scripts/emojilist.ts +++ b/packages/frontend-shared/js/emojilist.ts @@ -12,12 +12,12 @@ export type UnicodeEmojiDef = { } // initial converted from https://github.com/muan/emojilib/commit/242fe68be86ed6536843b83f7e32f376468b38fb -import _emojilist from '../emojilist.json'; +import _emojilist from './emojilist.json'; export const emojilist: UnicodeEmojiDef[] = _emojilist.map(x => ({ name: x[1] as string, char: x[0] as string, - category: unicodeEmojiCategories[x[2]], + category: unicodeEmojiCategories[x[2] as number], })); const unicodeEmojisMap = new Map( diff --git a/packages/frontend/src/scripts/extract-avg-color-from-blurhash.ts b/packages/frontend-shared/js/extract-avg-color-from-blurhash.ts similarity index 100% rename from packages/frontend/src/scripts/extract-avg-color-from-blurhash.ts rename to packages/frontend-shared/js/extract-avg-color-from-blurhash.ts diff --git a/packages/frontend/src/scripts/i18n.ts b/packages/frontend-shared/js/i18n.ts similarity index 78% rename from packages/frontend/src/scripts/i18n.ts rename to packages/frontend-shared/js/i18n.ts index c2f44a33cc..18232691fa 100644 --- a/packages/frontend/src/scripts/i18n.ts +++ b/packages/frontend-shared/js/i18n.ts @@ -2,7 +2,10 @@ * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ -import type { ILocale, ParameterizedString } from '../../../../locales/index.js'; +import type { ILocale, ParameterizedString } from '../../../locales/index.js'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type TODO = any; type FlattenKeys = keyof { [K in keyof T as T[K] extends ILocale @@ -32,15 +35,18 @@ type Tsx = { export class I18n { private tsxCache?: Tsx; + private devMode: boolean; + + constructor(public locale: T, devMode = false) { + this.devMode = devMode; - constructor(public locale: T) { //#region BIND this.t = this.t.bind(this); //#endregion } public get ts(): T { - if (_DEV_) { + if (this.devMode) { class Handler implements ProxyHandler { get(target: TTarget, p: string | symbol): unknown { const value = target[p as keyof TTarget]; @@ -72,7 +78,7 @@ export class I18n { } public get tsx(): Tsx { - if (_DEV_) { + if (this.devMode) { if (this.tsxCache) { return this.tsxCache; } @@ -113,7 +119,7 @@ export class I18n { return () => value; } - return (arg) => { + return (arg: TODO) => { let str = quasis[0]; for (let i = 0; i < expressions.length; i++) { @@ -137,7 +143,6 @@ export class I18n { return this.tsxCache = new Proxy(this.locale, new Handler()) as unknown as Tsx; } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (this.tsxCache) { return this.tsxCache; } @@ -153,7 +158,7 @@ export class I18n { const value = target[k as keyof typeof target]; if (typeof value === 'object') { - result[k] = build(value as ILocale); + (result as TODO)[k] = build(value as ILocale); } else if (typeof value === 'string') { const quasis: string[] = []; const expressions: string[] = []; @@ -180,7 +185,7 @@ export class I18n { continue; } - result[k] = (arg) => { + (result as TODO)[k] = (arg: TODO) => { let str = quasis[0]; for (let i = 0; i < expressions.length; i++) { @@ -209,9 +214,9 @@ export class I18n { let str: string | ParameterizedString | ILocale = this.locale; for (const k of key.split('.')) { - str = str[k]; + str = (str as TODO)[k]; - if (_DEV_) { + if (this.devMode) { if (typeof str === 'undefined') { console.error(`Unexpected locale key: ${key}`); return key; @@ -220,7 +225,7 @@ export class I18n { } if (args) { - if (_DEV_) { + if (this.devMode) { const missing = Array.from((str as string).matchAll(/\{(\w+)\}/g), ([, parameter]) => parameter).filter(parameter => !Object.hasOwn(args, parameter)); if (missing.length) { @@ -231,7 +236,7 @@ export class I18n { for (const [k, v] of Object.entries(args)) { const search = `{${k}}`; - if (_DEV_) { + if (this.devMode) { if (!(str as string).includes(search)) { console.error(`Unexpected locale parameter: ${k} at ${key}`); } @@ -244,51 +249,3 @@ export class I18n { return str; } } - -if (import.meta.vitest) { - const { describe, expect, it } = import.meta.vitest; - - describe('i18n', () => { - it('t', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.t('foo')).toBe('foo'); - expect(i18n.t('bar.baz')).toBe('baz'); - expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); - expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); - }); - it('ts', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.ts.foo).toBe('foo'); - expect(i18n.ts.bar.baz).toBe('baz'); - }); - it('tsx', () => { - const i18n = new I18n({ - foo: 'foo', - bar: { - baz: 'baz', - qux: 'qux {0}' as unknown as ParameterizedString<'0'>, - quux: 'quux {0} {1}' as unknown as ParameterizedString<'0' | '1'>, - }, - }); - - expect(i18n.tsx.bar.qux({ 0: 'hoge' })).toBe('qux hoge'); - expect(i18n.tsx.bar.quux({ 0: 'hoge', 1: 'fuga' })).toBe('quux hoge fuga'); - }); - }); -} diff --git a/packages/frontend-shared/js/intl-const.ts b/packages/frontend-shared/js/intl-const.ts new file mode 100644 index 0000000000..33b65b6e9b --- /dev/null +++ b/packages/frontend-shared/js/intl-const.ts @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { lang } from '@@/js/config.js'; + +// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition +export const versatileLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP'); + +let _dateTimeFormat: Intl.DateTimeFormat; +try { + _dateTimeFormat = new Intl.DateTimeFormat(versatileLang, { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + }); +} catch (err) { + console.warn(err); + if (_DEV_) console.log('[Intl] Fallback to en-US'); + + // Fallback to en-US + _dateTimeFormat = new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + }); +} +export const dateTimeFormat = _dateTimeFormat; + +export const timeZone = dateTimeFormat.resolvedOptions().timeZone; + +export const hemisphere = /^(australia|pacific|antarctica|indian)\//i.test(timeZone) ? 'S' : 'N'; + +let _numberFormat: Intl.NumberFormat; +try { + _numberFormat = new Intl.NumberFormat(versatileLang); +} catch (err) { + console.warn(err); + if (_DEV_) console.log('[Intl] Fallback to en-US'); + + // Fallback to en-US + _numberFormat = new Intl.NumberFormat('en-US'); +} +export const numberFormat = _numberFormat; diff --git a/packages/frontend-shared/js/is-link.ts b/packages/frontend-shared/js/is-link.ts new file mode 100644 index 0000000000..946f86400e --- /dev/null +++ b/packages/frontend-shared/js/is-link.ts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export function isLink(el: HTMLElement) { + if (el.tagName === 'A') return true; + if (el.parentElement) { + return isLink(el.parentElement); + } + return false; +} diff --git a/packages/frontend-shared/js/media-proxy.ts b/packages/frontend-shared/js/media-proxy.ts new file mode 100644 index 0000000000..2837870c9a --- /dev/null +++ b/packages/frontend-shared/js/media-proxy.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as Misskey from 'misskey-js'; +import { query } from './url.js'; + +export class MediaProxy { + private serverMetadata: Misskey.entities.MetaDetailed; + private url: string; + + constructor(serverMetadata: Misskey.entities.MetaDetailed, url: string) { + this.serverMetadata = serverMetadata; + this.url = url; + } + + public getProxiedImageUrl(imageUrl: string, type?: 'preview' | 'emoji' | 'avatar', mustOrigin = false, noFallback = false): string { + const localProxy = `${this.url}/proxy`; + let _imageUrl = imageUrl; + + if (imageUrl.startsWith(this.serverMetadata.mediaProxy + '/') || imageUrl.startsWith('/proxy/') || imageUrl.startsWith(localProxy + '/')) { + // もう既にproxyっぽそうだったらurlを取り出す + _imageUrl = (new URL(imageUrl)).searchParams.get('url') ?? imageUrl; + } + + return `${mustOrigin ? localProxy : this.serverMetadata.mediaProxy}/${ + type === 'preview' ? 'preview.webp' + : 'image.webp' + }?${query({ + url: _imageUrl, + ...(!noFallback ? { 'fallback': '1' } : {}), + ...(type ? { [type]: '1' } : {}), + ...(mustOrigin ? { origin: '1' } : {}), + })}`; + } + + public getProxiedImageUrlNullable(imageUrl: string | null | undefined, type?: 'preview'): string | null { + if (imageUrl == null) return null; + return this.getProxiedImageUrl(imageUrl, type); + } + + public getStaticImageUrl(baseUrl: string): string { + const u = baseUrl.startsWith('http') ? new URL(baseUrl) : new URL(baseUrl, this.url); + + if (u.href.startsWith(`${this.url}/emoji/`)) { + // もう既にemojiっぽそうだったらsearchParams付けるだけ + u.searchParams.set('static', '1'); + return u.href; + } + + if (u.href.startsWith(this.serverMetadata.mediaProxy + '/')) { + // もう既にproxyっぽそうだったらsearchParams付けるだけ + u.searchParams.set('static', '1'); + return u.href; + } + + return `${this.serverMetadata.mediaProxy}/static.webp?${query({ + url: u.href, + static: '1', + })}`; + } +} diff --git a/packages/frontend/src/scripts/scroll.ts b/packages/frontend-shared/js/scroll.ts similarity index 75% rename from packages/frontend/src/scripts/scroll.ts rename to packages/frontend-shared/js/scroll.ts index 8edb6fca05..4f2e9105c3 100644 --- a/packages/frontend/src/scripts/scroll.ts +++ b/packages/frontend-shared/js/scroll.ts @@ -23,24 +23,40 @@ export function getStickyTop(el: HTMLElement, container: HTMLElement | null = nu return getStickyTop(el.parentElement, container, newTop); } +export function getStickyBottom(el: HTMLElement, container: HTMLElement | null = null, bottom = 0) { + if (!el.parentElement) return bottom; + const data = el.dataset.stickyContainerFooterHeight; + const newBottom = data ? Number(data) + bottom : bottom; + if (el === container) return newBottom; + return getStickyBottom(el.parentElement, container, newBottom); +} + export function getScrollPosition(el: HTMLElement | null): number { const container = getScrollContainer(el); return container == null ? window.scrollY : container.scrollTop; } -export function onScrollTop(el: HTMLElement, cb: () => unknown, tolerance = 1, once = false) { +export function onScrollTop(el: HTMLElement, cb: (topVisible: boolean) => unknown, tolerance = 1, once = false) { // とりあえず評価してみる - if (el.isConnected && isTopVisible(el)) { - cb(); + const firstTopVisible = isTopVisible(el); + if (el.isConnected && firstTopVisible) { + cb(firstTopVisible); if (once) return null; } const container = getScrollContainer(el) ?? window; - const onScroll = ev => { + // 以下のケースにおいて、cbが何度も呼び出されてしまって具合が悪いので1回呼んだら以降は無視するようにする + // - スクロールイベントは1回のスクロールで複数回発生することがある + // - toleranceの範囲内に収まる程度の微量なスクロールが発生した + let prevTopVisible = firstTopVisible; + const onScroll = () => { if (!document.body.contains(el)) return; - if (isTopVisible(el, tolerance)) { - cb(); + + const topVisible = isTopVisible(el, tolerance); + if (topVisible !== prevTopVisible) { + prevTopVisible = topVisible; + cb(topVisible); if (once) removeListener(); } }; @@ -61,7 +77,7 @@ export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance = 1 } const containerOrWindow = container ?? window; - const onScroll = ev => { + const onScroll = () => { if (!document.body.contains(el)) return; if (isBottomVisible(el, 1, container)) { cb(); @@ -118,6 +134,7 @@ export function scrollToBottom( export function isTopVisible(el: HTMLElement, tolerance = 1): boolean { const scrollTop = getScrollPosition(el); + if (_DEV_) console.log(scrollTop, tolerance, scrollTop <= tolerance); return scrollTop <= tolerance; } diff --git a/packages/frontend/src/scripts/url.ts b/packages/frontend-shared/js/url.ts similarity index 55% rename from packages/frontend/src/scripts/url.ts rename to packages/frontend-shared/js/url.ts index e3072b3b7d..eb830b1eea 100644 --- a/packages/frontend/src/scripts/url.ts +++ b/packages/frontend-shared/js/url.ts @@ -8,16 +8,21 @@ * 2. プロパティがundefinedの時はクエリを付けない * (new URLSearchParams(obj)ではそこまで丁寧なことをしてくれない) */ -export function query(obj: Record): string { +export function query(obj: Record): string { const params = Object.entries(obj) - .filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined) - .reduce((a, [k, v]) => (a[k] = v, a), {} as Record); + .filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined) // eslint-disable-line @typescript-eslint/no-unnecessary-condition + .reduce>((a, [k, v]) => (a[k] = v, a), {}); return Object.entries(params) .map((p) => `${p[0]}=${encodeURIComponent(p[1])}`) .join('&'); } -export function appendQuery(url: string, query: string): string { - return `${url}${/\?/.test(url) ? url.endsWith('?') ? '' : '&' : '?'}${query}`; +export function appendQuery(url: string, queryString: string): string { + return `${url}${/\?/.test(url) ? url.endsWith('?') ? '' : '&' : '?'}${queryString}`; +} + +export function extractDomain(url: string) { + const match = url.match(/^(?:https?:)?(?:\/\/)?(?:[^@\n]+@)?([^:\/\n]+)/im); + return match ? match[1] : null; } diff --git a/packages/frontend/src/scripts/use-document-visibility.ts b/packages/frontend-shared/js/use-document-visibility.ts similarity index 85% rename from packages/frontend/src/scripts/use-document-visibility.ts rename to packages/frontend-shared/js/use-document-visibility.ts index a8f4d5e03a..b1197e68da 100644 --- a/packages/frontend/src/scripts/use-document-visibility.ts +++ b/packages/frontend-shared/js/use-document-visibility.ts @@ -3,7 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { onMounted, onUnmounted, ref, Ref } from 'vue'; +import { onMounted, onUnmounted, ref } from 'vue'; +import type { Ref } from 'vue'; export function useDocumentVisibility(): Ref { const visibility = ref(document.visibilityState); diff --git a/packages/frontend/src/scripts/use-interval.ts b/packages/frontend-shared/js/use-interval.ts similarity index 100% rename from packages/frontend/src/scripts/use-interval.ts rename to packages/frontend-shared/js/use-interval.ts diff --git a/packages/frontend/src/scripts/worker-multi-dispatch.ts b/packages/frontend-shared/js/worker-multi-dispatch.ts similarity index 84% rename from packages/frontend/src/scripts/worker-multi-dispatch.ts rename to packages/frontend-shared/js/worker-multi-dispatch.ts index 6b3fcd9383..5d393ed1ed 100644 --- a/packages/frontend/src/scripts/worker-multi-dispatch.ts +++ b/packages/frontend-shared/js/worker-multi-dispatch.ts @@ -3,16 +3,18 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -function defaultUseWorkerNumber(prev: number, totalWorkers: number) { +function defaultUseWorkerNumber(prev: number) { return prev + 1; } -export class WorkerMultiDispatch { +type WorkerNumberGetter = (prev: number, totalWorkers: number) => number; + +export class WorkerMultiDispatch { private symbol = Symbol('WorkerMultiDispatch'); private workers: Worker[] = []; private terminated = false; private prevWorkerNumber = 0; - private getUseWorkerNumber = defaultUseWorkerNumber; + private getUseWorkerNumber: WorkerNumberGetter; private finalizationRegistry: FinalizationRegistry; constructor(workerConstructor: () => Worker, concurrency: number, getUseWorkerNumber = defaultUseWorkerNumber) { @@ -29,7 +31,7 @@ export class WorkerMultiDispatch { if (_DEV_) console.log('WorkerMultiDispatch: Created', this); } - public postMessage(message: POST, options?: Transferable[] | StructuredSerializeOptions, useWorkerNumber: typeof defaultUseWorkerNumber = this.getUseWorkerNumber) { + public postMessage(message: POST, options?: Transferable[] | StructuredSerializeOptions, useWorkerNumber: WorkerNumberGetter = this.getUseWorkerNumber) { let workerNumber = useWorkerNumber(this.prevWorkerNumber, this.workers.length); workerNumber = Math.abs(Math.round(workerNumber)) % this.workers.length; if (_DEV_) console.log('WorkerMultiDispatch: Posting message to worker', workerNumber, useWorkerNumber); @@ -46,12 +48,14 @@ export class WorkerMultiDispatch { return workerNumber; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any public addListener(callback: (this: Worker, ev: MessageEvent) => any, options?: boolean | AddEventListenerOptions) { this.workers.forEach(worker => { worker.addEventListener('message', callback, options); }); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any public removeListener(callback: (this: Worker, ev: MessageEvent) => any, options?: boolean | AddEventListenerOptions) { this.workers.forEach(worker => { worker.removeEventListener('message', callback, options); diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json new file mode 100644 index 0000000000..9981d10dd2 --- /dev/null +++ b/packages/frontend-shared/package.json @@ -0,0 +1,39 @@ +{ + "name": "frontend-shared", + "type": "module", + "main": "./js-built/index.js", + "types": "./js-built/index.d.ts", + "exports": { + ".": { + "import": "./js-built/index.js", + "types": "./js-built/index.d.ts" + }, + "./*": { + "import": "./js-built/*", + "types": "./js-built/*" + } + }, + "scripts": { + "build": "node ./build.js", + "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", + "eslint": "eslint './**/*.{js,jsx,ts,tsx}'", + "typecheck": "tsc --noEmit", + "lint": "pnpm typecheck && pnpm eslint" + }, + "devDependencies": { + "@types/node": "20.14.12", + "@typescript-eslint/eslint-plugin": "7.17.0", + "@typescript-eslint/parser": "7.17.0", + "esbuild": "0.23.0", + "eslint-plugin-vue": "9.27.0", + "typescript": "5.5.4", + "vue-eslint-parser": "9.4.3" + }, + "files": [ + "js-built" + ], + "dependencies": { + "misskey-js": "workspace:*", + "vue": "3.4.37" + } +} diff --git a/packages/frontend/src/themes/_dark.json5 b/packages/frontend-shared/themes/_dark.json5 similarity index 85% rename from packages/frontend/src/themes/_dark.json5 rename to packages/frontend-shared/themes/_dark.json5 index c82a956868..5271785e62 100644 --- a/packages/frontend/src/themes/_dark.json5 +++ b/packages/frontend-shared/themes/_dark.json5 @@ -13,6 +13,7 @@ accentDarken: ':darken<10<@accent', accentLighten: ':lighten<10<@accent', accentedBg: ':alpha<0.15<@accent', + love: '#dd2e44', focus: ':alpha<0.3<@accent', bg: '#000', acrylicBg: ':alpha<0.5<@bg', @@ -29,7 +30,7 @@ panelHeaderBg: ':lighten<3<@panel', panelHeaderFg: '@fg', panelHeaderDivider: 'rgba(0, 0, 0, 0)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', acrylicPanel: ':alpha<0.5<@panel', windowHeader: ':alpha<0.85<@panel', popup: ':lighten<3<@panel', @@ -53,18 +54,19 @@ infoFg: '#fff', infoWarnBg: '#42321c', infoWarnFg: '#ffbd3e', - switchBg: 'rgba(255, 255, 255, 0.15)', - buttonBg: 'rgba(255, 255, 255, 0.05)', - buttonHoverBg: 'rgba(255, 255, 255, 0.1)', + folderHeaderBg: 'rgba(255, 255, 255, 0.05)', + folderHeaderHoverBg: 'rgba(255, 255, 255, 0.1)', + buttonBg: ':lighten<5<@panel', + buttonHoverBg: ':lighten<10<@panel', buttonGradateA: '@accent', buttonGradateB: ':hue<20<@accent', + switchBg: 'rgba(255, 255, 255, 0.15)', switchOffBg: 'rgba(255, 255, 255, 0.1)', switchOffFg: ':alpha<0.8<@fg', switchOnBg: '@accentedBg', switchOnFg: '@accent', inputBorder: 'rgba(255, 255, 255, 0.1)', inputBorderHover: 'rgba(255, 255, 255, 0.2)', - listItemHoverBg: 'rgba(255, 255, 255, 0.03)', driveFolderBg: ':alpha<0.3<@accent', wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', badge: '#31b1ce', @@ -77,22 +79,14 @@ codeBoolean: '#c59eff', deckBg: '#000', htmlThemeColor: '@bg', - X2: ':darken<2<@panel', X3: 'rgba(255, 255, 255, 0.05)', X4: 'rgba(255, 255, 255, 0.1)', X5: 'rgba(255, 255, 255, 0.05)', X6: 'rgba(255, 255, 255, 0.15)', X7: 'rgba(255, 255, 255, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', - X10: ':alpha<0.4<@accent', X11: 'rgba(0, 0, 0, 0.3)', X12: 'rgba(255, 255, 255, 0.1)', X13: 'rgba(255, 255, 255, 0.15)', - X14: ':alpha<0.5<@navBg', - X15: ':alpha<0<@panel', - X16: ':alpha<0.7<@panel', - X17: ':alpha<0.8<@bg', }, codeHighlighter: { diff --git a/packages/frontend/src/themes/_light.json5 b/packages/frontend-shared/themes/_light.json5 similarity index 86% rename from packages/frontend/src/themes/_light.json5 rename to packages/frontend-shared/themes/_light.json5 index 63bc030916..be331ce58f 100644 --- a/packages/frontend/src/themes/_light.json5 +++ b/packages/frontend-shared/themes/_light.json5 @@ -13,6 +13,7 @@ accentDarken: ':darken<10<@accent', accentLighten: ':lighten<10<@accent', accentedBg: ':alpha<0.15<@accent', + love: '#dd2e44', focus: ':alpha<0.3<@accent', bg: '#fff', acrylicBg: ':alpha<0.5<@bg', @@ -29,7 +30,7 @@ panelHeaderBg: ':lighten<3<@panel', panelHeaderFg: '@fg', panelHeaderDivider: 'rgba(0, 0, 0, 0)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', acrylicPanel: ':alpha<0.5<@panel', windowHeader: ':alpha<0.85<@panel', popup: ':lighten<3<@panel', @@ -53,18 +54,19 @@ infoFg: '#72818a', infoWarnBg: '#fff0db', infoWarnFg: '#8f6e31', - switchBg: 'rgba(0, 0, 0, 0.15)', - buttonBg: 'rgba(0, 0, 0, 0.05)', - buttonHoverBg: 'rgba(0, 0, 0, 0.1)', + folderHeaderBg: 'rgba(0, 0, 0, 0.05)', + folderHeaderHoverBg: 'rgba(0, 0, 0, 0.1)', + buttonBg: ':darken<5<@panel', + buttonHoverBg: ':darken<10<@panel', buttonGradateA: '@accent', buttonGradateB: ':hue<20<@accent', + switchBg: 'rgba(0, 0, 0, 0.15)', switchOffBg: 'rgba(0, 0, 0, 0.1)', switchOffFg: '@panel', switchOnBg: '@accent', switchOnFg: '@fgOnAccent', inputBorder: 'rgba(0, 0, 0, 0.1)', inputBorderHover: 'rgba(0, 0, 0, 0.2)', - listItemHoverBg: 'rgba(0, 0, 0, 0.03)', driveFolderBg: ':alpha<0.3<@accent', wallpaperOverlay: 'rgba(255, 255, 255, 0.5)', badge: '#31b1ce', @@ -77,22 +79,14 @@ codeBoolean: '#62b70c', deckBg: ':darken<3<@bg', htmlThemeColor: '@bg', - X2: ':darken<2<@panel', X3: 'rgba(0, 0, 0, 0.05)', X4: 'rgba(0, 0, 0, 0.1)', X5: 'rgba(0, 0, 0, 0.05)', X6: 'rgba(0, 0, 0, 0.25)', X7: 'rgba(0, 0, 0, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', - X10: ':alpha<0.4<@accent', X11: 'rgba(0, 0, 0, 0.1)', X12: 'rgba(0, 0, 0, 0.1)', X13: 'rgba(0, 0, 0, 0.15)', - X14: ':alpha<0.5<@navBg', - X15: ':alpha<0<@panel', - X16: ':alpha<0.7<@panel', - X17: ':alpha<0.8<@bg', }, codeHighlighter: { diff --git a/packages/frontend/src/themes/d-astro.json5 b/packages/frontend-shared/themes/d-astro.json5 similarity index 82% rename from packages/frontend/src/themes/d-astro.json5 rename to packages/frontend-shared/themes/d-astro.json5 index fee25cc4a4..4422526a33 100644 --- a/packages/frontend/src/themes/d-astro.json5 +++ b/packages/frontend-shared/themes/d-astro.json5 @@ -25,7 +25,6 @@ mention: '#ffd152', modalBg: 'rgba(0, 0, 0, 0.5)', success: '#86b300', - buttonBg: 'rgba(255, 255, 255, 0.05)', acrylicBg: ':alpha<0.5<@bg', indicator: '@accent', mentionMe: '#fb5d38', @@ -37,12 +36,11 @@ dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', inputBorderHover: 'rgba(255, 255, 255, 0.2)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', accentDarken: ':darken<10<@accent', acrylicPanel: ':alpha<0.5<@panel', navIndicator: '@accent', accentLighten: ':lighten<10<@accent', - buttonHoverBg: 'rgba(255, 255, 255, 0.1)', buttonGradateA: '@accent', buttonGradateB: ':hue<-20<@accent', driveFolderBg: ':alpha<0.3<@accent', @@ -52,25 +50,17 @@ htmlThemeColor: '@bg', fgOnWhite: '@accent', panelHighlight: ':lighten<3<@panel', - listItemHoverBg: 'rgba(255, 255, 255, 0.03)', scrollbarHandle: 'rgba(255, 255, 255, 0.2)', wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', panelHeaderDivider: 'rgba(0, 0, 0, 0)', scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)', - X2: ':darken<2<@panel', X3: 'rgba(255, 255, 255, 0.05)', X4: 'rgba(255, 255, 255, 0.1)', X5: 'rgba(255, 255, 255, 0.05)', X6: 'rgba(255, 255, 255, 0.15)', X7: 'rgba(255, 255, 255, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', - X10: ':alpha<0.4<@accent', X11: 'rgba(0, 0, 0, 0.3)', X12: 'rgba(255, 255, 255, 0.1)', X13: 'rgba(255, 255, 255, 0.15)', - X14: ':alpha<0.5<@navBg', - X15: ':alpha<0<@panel', - X16: ':alpha<0.7<@panel', }, } diff --git a/packages/frontend/src/themes/d-botanical.json5 b/packages/frontend-shared/themes/d-botanical.json5 similarity index 100% rename from packages/frontend/src/themes/d-botanical.json5 rename to packages/frontend-shared/themes/d-botanical.json5 diff --git a/packages/frontend/src/themes/d-cherry.json5 b/packages/frontend-shared/themes/d-cherry.json5 similarity index 100% rename from packages/frontend/src/themes/d-cherry.json5 rename to packages/frontend-shared/themes/d-cherry.json5 diff --git a/packages/frontend/src/themes/d-dark.json5 b/packages/frontend-shared/themes/d-dark.json5 similarity index 100% rename from packages/frontend/src/themes/d-dark.json5 rename to packages/frontend-shared/themes/d-dark.json5 diff --git a/packages/frontend/src/themes/d-future.json5 b/packages/frontend-shared/themes/d-future.json5 similarity index 100% rename from packages/frontend/src/themes/d-future.json5 rename to packages/frontend-shared/themes/d-future.json5 diff --git a/packages/frontend/src/themes/d-green-lime.json5 b/packages/frontend-shared/themes/d-green-lime.json5 similarity index 100% rename from packages/frontend/src/themes/d-green-lime.json5 rename to packages/frontend-shared/themes/d-green-lime.json5 diff --git a/packages/frontend/src/themes/d-green-orange.json5 b/packages/frontend-shared/themes/d-green-orange.json5 similarity index 100% rename from packages/frontend/src/themes/d-green-orange.json5 rename to packages/frontend-shared/themes/d-green-orange.json5 diff --git a/packages/frontend/src/themes/d-ice.json5 b/packages/frontend-shared/themes/d-ice.json5 similarity index 100% rename from packages/frontend/src/themes/d-ice.json5 rename to packages/frontend-shared/themes/d-ice.json5 diff --git a/packages/frontend/src/themes/d-persimmon.json5 b/packages/frontend-shared/themes/d-persimmon.json5 similarity index 100% rename from packages/frontend/src/themes/d-persimmon.json5 rename to packages/frontend-shared/themes/d-persimmon.json5 diff --git a/packages/frontend/src/themes/d-u0.json5 b/packages/frontend-shared/themes/d-u0.json5 similarity index 89% rename from packages/frontend/src/themes/d-u0.json5 rename to packages/frontend-shared/themes/d-u0.json5 index 3bd0b9483c..fb707c74c3 100644 --- a/packages/frontend/src/themes/d-u0.json5 +++ b/packages/frontend-shared/themes/d-u0.json5 @@ -3,14 +3,11 @@ base: 'dark', name: 'Mi U0 Dark', props: { - X2: ':darken<2<@panel', X3: 'rgba(255, 255, 255, 0.05)', X4: 'rgba(255, 255, 255, 0.1)', X5: 'rgba(255, 255, 255, 0.05)', X6: 'rgba(255, 255, 255, 0.15)', X7: 'rgba(255, 255, 255, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', bg: '#172426', fg: '#dadada', X10: ':alpha<0.4<@accent', @@ -41,7 +38,6 @@ mention: '@accent', modalBg: 'rgba(0, 0, 0, 0.5)', success: '#86b300', - buttonBg: 'rgba(255, 255, 255, 0.05)', switchBg: 'rgba(255, 255, 255, 0.15)', acrylicBg: ':alpha<0.5<@bg', indicator: '@accent', @@ -59,12 +55,11 @@ codeBoolean: '#c59eff', dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', accentDarken: ':darken<10<@accent', acrylicPanel: ':alpha<0.5<@panel', navIndicator: '@indicator', accentLighten: ':lighten<10<@accent', - buttonHoverBg: 'rgba(255, 255, 255, 0.1)', driveFolderBg: ':alpha<0.3<@accent', fgHighlighted: ':lighten<3<@fg', fgTransparent: ':alpha<0.5<@fg', @@ -74,7 +69,6 @@ buttonGradateB: ':hue<20<@accent', htmlThemeColor: '@bg', panelHighlight: ':lighten<3<@panel', - listItemHoverBg: 'rgba(255, 255, 255, 0.03)', scrollbarHandle: 'rgba(255, 255, 255, 0.2)', inputBorderHover: 'rgba(255, 255, 255, 0.2)', wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', diff --git a/packages/frontend/src/themes/l-apricot.json5 b/packages/frontend-shared/themes/l-apricot.json5 similarity index 100% rename from packages/frontend/src/themes/l-apricot.json5 rename to packages/frontend-shared/themes/l-apricot.json5 diff --git a/packages/frontend/src/themes/l-botanical.json5 b/packages/frontend-shared/themes/l-botanical.json5 similarity index 100% rename from packages/frontend/src/themes/l-botanical.json5 rename to packages/frontend-shared/themes/l-botanical.json5 diff --git a/packages/frontend/src/themes/l-cherry.json5 b/packages/frontend-shared/themes/l-cherry.json5 similarity index 100% rename from packages/frontend/src/themes/l-cherry.json5 rename to packages/frontend-shared/themes/l-cherry.json5 diff --git a/packages/frontend/src/themes/l-coffee.json5 b/packages/frontend-shared/themes/l-coffee.json5 similarity index 100% rename from packages/frontend/src/themes/l-coffee.json5 rename to packages/frontend-shared/themes/l-coffee.json5 diff --git a/packages/frontend/src/themes/l-light.json5 b/packages/frontend-shared/themes/l-light.json5 similarity index 100% rename from packages/frontend/src/themes/l-light.json5 rename to packages/frontend-shared/themes/l-light.json5 diff --git a/packages/frontend/src/themes/l-rainy.json5 b/packages/frontend-shared/themes/l-rainy.json5 similarity index 100% rename from packages/frontend/src/themes/l-rainy.json5 rename to packages/frontend-shared/themes/l-rainy.json5 diff --git a/packages/frontend/src/themes/l-sushi.json5 b/packages/frontend-shared/themes/l-sushi.json5 similarity index 100% rename from packages/frontend/src/themes/l-sushi.json5 rename to packages/frontend-shared/themes/l-sushi.json5 diff --git a/packages/frontend/src/themes/l-u0.json5 b/packages/frontend-shared/themes/l-u0.json5 similarity index 92% rename from packages/frontend/src/themes/l-u0.json5 rename to packages/frontend-shared/themes/l-u0.json5 index dbc777d493..7062e7fe5b 100644 --- a/packages/frontend/src/themes/l-u0.json5 +++ b/packages/frontend-shared/themes/l-u0.json5 @@ -3,14 +3,11 @@ base: 'light', name: 'Mi U0 Light', props: { - X2: ':darken<2<@panel', X3: 'rgba(255, 255, 255, 0.05)', X4: 'rgba(255, 255, 255, 0.1)', X5: 'rgba(255, 255, 255, 0.05)', X6: 'rgba(255, 255, 255, 0.15)', X7: 'rgba(255, 255, 255, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', bg: '#e7e7eb', fg: '#5f5f5f', X10: ':alpha<0.4<@accent', @@ -59,7 +56,7 @@ codeBoolean: '#c59eff', dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', accentDarken: ':darken<10<@accent', acrylicPanel: ':alpha<0.5<@panel', navIndicator: '@indicator', @@ -74,7 +71,6 @@ buttonGradateB: ':hue<20<@accent', htmlThemeColor: '@bg', panelHighlight: ':lighten<3<@panel', - listItemHoverBg: 'rgba(255, 255, 255, 0.03)', scrollbarHandle: '#74747433', inputBorderHover: 'rgba(255, 255, 255, 0.2)', wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', diff --git a/packages/frontend/src/themes/l-vivid.json5 b/packages/frontend-shared/themes/l-vivid.json5 similarity index 82% rename from packages/frontend/src/themes/l-vivid.json5 rename to packages/frontend-shared/themes/l-vivid.json5 index 3368855b5e..39768d4ac6 100644 --- a/packages/frontend/src/themes/l-vivid.json5 +++ b/packages/frontend-shared/themes/l-vivid.json5 @@ -28,7 +28,6 @@ mention: '@accent', modalBg: 'rgba(0, 0, 0, 0.3)', success: '#86b300', - buttonBg: 'rgba(0, 0, 0, 0.05)', acrylicBg: ':alpha<0.5<@bg', indicator: '@accent', mentionMe: '@mention', @@ -40,12 +39,11 @@ dateLabelFg: '@fg', inputBorder: 'rgba(0, 0, 0, 0.1)', inputBorderHover: 'rgba(0, 0, 0, 0.2)', - panelBorder: '" solid 1px var(--divider)', + panelBorder: '" solid 1px var(--MI_THEME-divider)', accentDarken: ':darken<10<@accent', acrylicPanel: ':alpha<0.5<@panel', navIndicator: '@accent', accentLighten: ':lighten<10<@accent', - buttonHoverBg: 'rgba(0, 0, 0, 0.1)', driveFolderBg: ':alpha<0.3<@accent', fgHighlighted: ':darken<3<@fg', fgTransparent: ':alpha<0.5<@fg', @@ -54,27 +52,18 @@ panelHeaderFg: '@fg', htmlThemeColor: '@bg', panelHighlight: ':darken<3<@panel', - listItemHoverBg: 'rgba(0, 0, 0, 0.03)', scrollbarHandle: 'rgba(0, 0, 0, 0.2)', wallpaperOverlay: 'rgba(255, 255, 255, 0.5)', fgTransparentWeak: ':alpha<0.75<@fg', panelHeaderDivider: '@divider', scrollbarHandleHover: 'rgba(0, 0, 0, 0.4)', - X2: ':darken<2<@panel', X3: 'rgba(0, 0, 0, 0.05)', X4: 'rgba(0, 0, 0, 0.1)', X5: 'rgba(0, 0, 0, 0.05)', X6: 'rgba(0, 0, 0, 0.25)', X7: 'rgba(0, 0, 0, 0.05)', - X8: ':lighten<5<@accent', - X9: ':darken<5<@accent', - X10: ':alpha<0.4<@accent', X11: 'rgba(0, 0, 0, 0.1)', X12: 'rgba(0, 0, 0, 0.1)', X13: 'rgba(0, 0, 0, 0.15)', - X14: ':alpha<0.5<@navBg', - X15: ':alpha<0<@panel', - X16: ':alpha<0.7<@panel', - X17: ':alpha<0.8<@bg', }, } diff --git a/packages/frontend-shared/tsconfig.json b/packages/frontend-shared/tsconfig.json new file mode 100644 index 0000000000..09a8ff76aa --- /dev/null +++ b/packages/frontend-shared/tsconfig.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ES2022", + "module": "nodenext", + "moduleResolution": "nodenext", + "declaration": true, + "declarationMap": true, + "sourceMap": false, + "outDir": "./js-built/", + "removeComments": true, + "resolveJsonModule": true, + "strict": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "experimentalDecorators": true, + "noImplicitReturns": true, + "esModuleInterop": true, + "baseUrl": ".", + "paths": { + "@/*": ["./*"], + "@@/*": ["./*"] + }, + "typeRoots": [ + "./@types", + "./node_modules/@types" + ], + "lib": [ + "esnext", + "dom" + ] + }, + "include": [ + "@types/**/*.ts", + "js/**/*" + ], + "exclude": [ + "node_modules", + "test/**/*" + ] +} diff --git a/packages/frontend/.eslintrc.cjs b/packages/frontend/.eslintrc.cjs deleted file mode 100644 index fd562e1c40..0000000000 --- a/packages/frontend/.eslintrc.cjs +++ /dev/null @@ -1,82 +0,0 @@ -module.exports = { - root: true, - env: { - 'node': false, - }, - parser: 'vue-eslint-parser', - parserOptions: { - 'parser': '@typescript-eslint/parser', - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - extraFileExtensions: ['.vue'], - }, - extends: [ - '../shared/.eslintrc.js', - 'plugin:vue/vue3-recommended', - ], - rules: { - '@typescript-eslint/no-empty-interface': [ - 'error', - { - 'allowSingleExtends': true, - }, - ], - // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため - // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため - 'id-denylist': ['error', 'window', 'e'], - 'no-shadow': ['warn'], - 'vue/attributes-order': ['error', { - 'alphabetical': false, - }], - 'vue/no-use-v-if-with-v-for': ['error', { - 'allowUsingIterationVar': false, - }], - 'vue/no-ref-as-operand': 'error', - 'vue/no-multi-spaces': ['error', { - 'ignoreProperties': false, - }], - 'vue/no-v-html': 'warn', - 'vue/order-in-components': 'error', - 'vue/html-indent': ['warn', 'tab', { - 'attribute': 1, - 'baseIndent': 0, - 'closeBracket': 0, - 'alignAttributesVertically': true, - 'ignores': [], - }], - 'vue/html-closing-bracket-spacing': ['warn', { - 'startTag': 'never', - 'endTag': 'never', - 'selfClosingTag': 'never', - }], - 'vue/multi-word-component-names': 'warn', - 'vue/require-v-for-key': 'warn', - 'vue/no-unused-components': 'warn', - 'vue/no-unused-vars': 'warn', - 'vue/no-dupe-keys': 'warn', - 'vue/valid-v-for': 'warn', - 'vue/return-in-computed-property': 'warn', - 'vue/no-setup-props-reactivity-loss': 'warn', - 'vue/max-attributes-per-line': 'off', - 'vue/html-self-closing': 'off', - 'vue/singleline-html-element-content-newline': 'off', - 'vue/v-on-event-hyphenation': ['error', 'never', { autofix: true }], - 'vue/attribute-hyphenation': ['error', 'never'], - }, - globals: { - // Node.js - 'module': false, - 'require': false, - '__dirname': false, - - // Misskey - '_DEV_': false, - '_LANGS_': false, - '_VERSION_': false, - '_ENV_': false, - '_PERF_PREFIX_': false, - '_DATA_TRANSFER_DRIVE_FILE_': false, - '_DATA_TRANSFER_DRIVE_FOLDER_': false, - '_DATA_TRANSFER_DECK_COLUMN_': false, - }, -}; diff --git a/packages/frontend/.storybook/changes.ts b/packages/frontend/.storybook/changes.ts index 7c70972e1e..1299910499 100644 --- a/packages/frontend/.storybook/changes.ts +++ b/packages/frontend/.storybook/changes.ts @@ -47,14 +47,12 @@ await fs.readFile( ) ) .map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, '')) - .map((path) => (path.startsWith('.') ? path : `./${path}`)) ); if ( micromatch(Array.from(modules), [ '../../assets/**', '../../fluent-emojis/**', '../../locales/ja-JP.yml', - '../../misskey-assets/**', 'assets/**', 'public/**', '../../pnpm-lock.yaml', diff --git a/packages/frontend/.storybook/fakes.ts b/packages/frontend/.storybook/fakes.ts index 9d789a34ff..fc3b0334e4 100644 --- a/packages/frontend/.storybook/fakes.ts +++ b/packages/frontend/.storybook/fakes.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { AISCRIPT_VERSION } from '@syuilo/aiscript'; import type { entities } from 'misskey-js' export function abuseUserReport() { @@ -47,18 +48,7 @@ export function clip(id = 'someclipid', name = 'Some Clip'): entities.Clip { createdAt: '2016-12-28T22:49:51.000Z', lastClippedAt: null, userId: 'someuserid', - user: { - id: 'someuserid', - name: 'Misskey User', - username: 'miskist', - host: 'misskey-hub.net', - avatarUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/about-icon.png?raw=true', - avatarBlurhash: 'eQFRshof5NWBRi},juayfPju53WB?0ofs;s*a{ofjuay^SoMEJR%ay', - avatarDecorations: [], - emojis: {}, - badgeRoles: [], - onlineStatus: 'unknown', - }, + user: userLite(), notesCount: undefined, name, description: 'Some clip description', @@ -125,6 +115,49 @@ export function file(isSensitive = false) { }; } +const script = `/// @ ${AISCRIPT_VERSION} + +var name = "" + +Ui:render([ + Ui:C:textInput({ + label: "Your name" + onInput: @(v) { name = v } + }) + Ui:C:button({ + text: "Hello" + onClick: @() { + Mk:dialog(null, \`Hello, {name}!\`) + } + }) +]) +`; + +export function flash(): entities.Flash { + return { + id: 'someflashid', + createdAt: '2016-12-28T22:49:51.000Z', + updatedAt: '2016-12-28T22:49:51.000Z', + userId: 'someuserid', + user: userLite(), + title: 'Some Play title', + summary: 'Some Play summary', + script, + visibility: 'public', + likedCount: 0, + isLiked: false, + }; +} + +export function folder(id = 'somefolderid', name = 'Some Folder', parentId: string | null = null): entities.DriveFolder { + return { + id, + createdAt: '2016-12-28T22:49:51.000Z', + name, + parentId, + }; +} + export function federationInstance(): entities.FederationInstance { return { id: 'someinstanceid', @@ -154,7 +187,27 @@ export function federationInstance(): entities.FederationInstance { }; } -export function userDetailed(id = 'someuserid', username = 'miskist', host = 'misskey-hub.net', name = 'Misskey User'): entities.UserDetailed { +export function note(id = 'somenoteid'): entities.Note { + return { + id, + createdAt: '2016-12-28T22:49:51.000Z', + deletedAt: null, + text: 'some note', + cw: null, + userId: 'someuserid', + user: userLite(), + visibility: 'public', + reactionAcceptance: 'nonSensitiveOnly', + reactionEmojis: {}, + reactions: {}, + myReaction: null, + reactionCount: 0, + renoteCount: 0, + repliesCount: 0, + }; +} + +export function userLite(id = 'someuserid', username = 'miskist', host: entities.UserDetailed['host'] = 'misskey-hub.net', name: entities.UserDetailed['name'] = 'Misskey User'): entities.UserLite { return { id, username, @@ -165,6 +218,12 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host = 'mi avatarBlurhash: 'eQFRshof5NWBRi},juayfPju53WB?0ofs;s*a{ofjuay^SoMEJR%ay', avatarDecorations: [], emojis: {}, + }; +} + +export function userDetailed(id = 'someuserid', username = 'miskist', host: entities.UserDetailed['host'] = 'misskey-hub.net', name: entities.UserDetailed['name'] = 'Misskey User'): entities.UserDetailed { + return { + ...userLite(id, username, host, name), bannerBlurhash: 'eQA^IW^-MH8w9tE8I=S^o{$*R4RikXtSxutRozjEnNR.RQadoyozog', bannerUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true', birthday: '2014-06-20', @@ -215,7 +274,7 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host = 'mi movedTo: null, alsoKnownAs: null, notify: 'none', - memo: null + memo: null, }; } diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx index 7b6c86447e..f2bdc631d2 100644 --- a/packages/frontend/.storybook/generate.tsx +++ b/packages/frontend/.storybook/generate.tsx @@ -397,15 +397,28 @@ function toStories(component: string): Promise { const globs = await Promise.all([ glob('src/components/global/Mk*.vue'), glob('src/components/global/RouterView.vue'), - glob('src/components/Mk[A-C]*.vue'), - glob('src/components/MkDigitalClock.vue'), + glob('src/components/MkAbuseReportWindow.vue'), + glob('src/components/MkAccountMoved.vue'), + glob('src/components/MkAchievements.vue'), + glob('src/components/MkAnalogClock.vue'), + glob('src/components/MkAnimBg.vue'), + glob('src/components/MkAnnouncementDialog.vue'), + glob('src/components/MkAntennaEditor.vue'), + glob('src/components/MkAntennaEditorDialog.vue'), + glob('src/components/MkAsUi.vue'), + glob('src/components/MkAutocomplete.vue'), + glob('src/components/MkAvatars.vue'), + glob('src/components/Mk[B-E]*.vue'), + glob('src/components/MkFlashPreview.vue'), glob('src/components/MkGalleryPostPreview.vue'), glob('src/components/MkSignupServerRules.vue'), glob('src/components/MkUserSetupDialog.vue'), glob('src/components/MkUserSetupDialog.*.vue'), glob('src/components/MkInstanceCardMini.vue'), glob('src/components/MkInviteCode.vue'), + glob('src/pages/admin/overview.ap-requests.vue'), glob('src/pages/user/home.vue'), + glob('src/pages/search.vue'), ]); const components = globs.flat(); await Promise.all(components.map(async (component) => { diff --git a/packages/frontend/.storybook/preload-theme.ts b/packages/frontend/.storybook/preload-theme.ts index fb93d7be13..e5573f2ac3 100644 --- a/packages/frontend/.storybook/preload-theme.ts +++ b/packages/frontend/.storybook/preload-theme.ts @@ -30,7 +30,7 @@ const keys = [ 'd-u0', ] -await Promise.all(keys.map((key) => readFile(new URL(`../src/themes/${key}.json5`, import.meta.url), 'utf8'))).then((sources) => { +await Promise.all(keys.map((key) => readFile(new URL(`../../frontend-shared/themes/${key}.json5`, import.meta.url), 'utf8'))).then((sources) => { writeFile( new URL('./themes.ts', import.meta.url), `export default ${JSON.stringify( diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts index 73ee007fb8..d000a28232 100644 --- a/packages/frontend/.storybook/preview.ts +++ b/packages/frontend/.storybook/preview.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { FORCE_REMOUNT } from '@storybook/core-events'; +import { FORCE_RE_RENDER, FORCE_REMOUNT } from '@storybook/core-events'; import { addons } from '@storybook/preview-api'; import { type Preview, setup } from '@storybook/vue3'; import isChromatic from 'chromatic/isChromatic'; @@ -16,7 +16,7 @@ import '../src/style.scss'; const appInitialized = Symbol(); -let lastStory = null; +let lastStory: string | null = null; let moduleInitialized = false; let unobserve = () => {}; let misskeyOS = null; @@ -110,7 +110,7 @@ const preview = { }).catch(() => {}); Promise.all([resetIndexedDBPromise, resetDefaultStorePromise]).then(() => { initLocalStorage(); - channel.emit(FORCE_REMOUNT, { storyId: context.id }); + channel.emit(FORCE_RE_RENDER, { storyId: context.id }); }); } const story = Story(); diff --git a/packages/frontend/@types/theme.d.ts b/packages/frontend/@types/theme.d.ts index 0a7281898d..70afc356c1 100644 --- a/packages/frontend/@types/theme.d.ts +++ b/packages/frontend/@types/theme.d.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -declare module '@/themes/*.json5' { +declare module '@@/themes/*.json5' { import { Theme } from '@/scripts/theme.js'; const theme: Theme; diff --git a/packages/frontend/assets/testcaptcha.png b/packages/frontend/assets/testcaptcha.png new file mode 100644 index 0000000000000000000000000000000000000000..9bfd252b51c6057f99ff1012897c4d9e6971f897 GIT binary patch literal 2634 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 Oz~JfX=d#Wzp$P!C^WPW% literal 0 HcmV?d00001 diff --git a/packages/frontend/eslint.config.js b/packages/frontend/eslint.config.js new file mode 100644 index 0000000000..dd8f03dac5 --- /dev/null +++ b/packages/frontend/eslint.config.js @@ -0,0 +1,95 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import parser from 'vue-eslint-parser'; +import pluginVue from 'eslint-plugin-vue'; +import pluginMisskey from '@misskey-dev/eslint-plugin'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['src/**/*.vue'], + ...pluginMisskey.configs.typescript, + }, + ...pluginVue.configs['flat/recommended'], + { + files: ['src/**/*.{ts,vue}'], + languageOptions: { + globals: { + ...Object.fromEntries(Object.entries(globals.node).map(([key]) => [key, 'off'])), + ...globals.browser, + + // Node.js + module: false, + require: false, + __dirname: false, + + // Misskey + _DEV_: false, + _LANGS_: false, + _VERSION_: false, + _ENV_: false, + _PERF_PREFIX_: false, + _DATA_TRANSFER_DRIVE_FILE_: false, + _DATA_TRANSFER_DRIVE_FOLDER_: false, + _DATA_TRANSFER_DECK_COLUMN_: false, + }, + parser, + parserOptions: { + extraFileExtensions: ['.vue'], + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-empty-interface': ['error', { + allowSingleExtends: true, + }], + // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため + // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため + 'id-denylist': ['error', 'window', 'e'], + 'no-shadow': ['warn'], + 'vue/attributes-order': ['error', { + alphabetical: false, + }], + 'vue/no-use-v-if-with-v-for': ['error', { + allowUsingIterationVar: false, + }], + 'vue/no-ref-as-operand': 'error', + 'vue/no-multi-spaces': ['error', { + ignoreProperties: false, + }], + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'error', + 'vue/html-indent': ['warn', 'tab', { + attribute: 1, + baseIndent: 0, + closeBracket: 0, + alignAttributesVertically: true, + ignores: [], + }], + 'vue/html-closing-bracket-spacing': ['warn', { + startTag: 'never', + endTag: 'never', + selfClosingTag: 'never', + }], + 'vue/multi-word-component-names': 'warn', + 'vue/require-v-for-key': 'warn', + 'vue/no-unused-components': 'warn', + 'vue/no-unused-vars': 'warn', + 'vue/no-dupe-keys': 'warn', + 'vue/valid-v-for': 'warn', + 'vue/return-in-computed-property': 'warn', + 'vue/no-setup-props-reactivity-loss': 'warn', + 'vue/max-attributes-per-line': 'off', + 'vue/html-self-closing': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/v-on-event-hyphenation': ['error', 'never', { + autofix: true, + }], + 'vue/attribute-hyphenation': ['error', 'never'], + }, + }, +]; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index a63d97658b..3226a554a9 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -17,35 +17,35 @@ "lint": "pnpm typecheck && pnpm eslint" }, "dependencies": { - "@discordapp/twemoji": "15.0.3", + "@discordapp/twemoji": "15.1.0", "@github/webauthn-json": "2.1.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@misskey-dev/browser-image-resizer": "2024.1.0", "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-replace": "5.0.5", - "@rollup/pluginutils": "5.1.0", - "@syuilo/aiscript": "0.18.0", + "@rollup/plugin-replace": "5.0.7", + "@rollup/pluginutils": "5.1.2", + "@syuilo/aiscript": "0.19.0", "@tabler/icons-webfont": "3.3.0", "@twemoji/parser": "15.1.1", - "@vitejs/plugin-vue": "5.0.4", - "@vue/compiler-sfc": "3.4.26", - "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.9", - "astring": "1.8.6", + "@vitejs/plugin-vue": "5.1.4", + "@vue/compiler-sfc": "3.5.11", + "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.11", + "astring": "1.9.0", "broadcast-channel": "7.0.0", "buraha": "0.0.1", "canvas-confetti": "1.9.3", - "chart.js": "4.4.2", + "chart.js": "4.4.4", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-matrix": "2.0.1", "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.0.1", - "chromatic": "11.3.0", - "compare-versions": "6.1.0", - "cropperjs": "2.0.0-beta.5", + "chromatic": "11.11.0", + "compare-versions": "6.1.1", + "cropperjs": "2.0.0-rc.2", "date-fns": "2.30.0", - "escape-regexp": "0.0.1", "estree-walker": "3.0.3", "eventemitter3": "5.0.1", + "frontend-shared": "workspace:*", "idb-keyval": "6.2.1", "insert-text-at-cursor": "0.3.0", "is-file-animated": "1.0.2", @@ -55,89 +55,87 @@ "misskey-bubble-game": "workspace:*", "misskey-js": "workspace:*", "misskey-reversi": "workspace:*", - "photoswipe": "5.4.3", + "photoswipe": "5.4.4", "punycode": "2.3.1", - "rollup": "4.17.2", - "sanitize-html": "2.13.0", - "sass": "1.76.0", - "shiki": "1.4.0", + "rollup": "4.22.5", + "sanitize-html": "2.13.1", + "sass": "1.79.3", + "shiki": "1.21.0", "strict-event-emitter-types": "2.0.0", "textarea-caret": "3.1.0", - "three": "0.164.1", - "throttle-debounce": "5.0.0", + "three": "0.169.0", + "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", - "tsc-alias": "1.8.8", + "tsc-alias": "1.8.10", "tsconfig-paths": "4.2.0", - "typescript": "5.5.2", - "uuid": "9.0.1", - "v-code-diff": "1.11.0", - "vite": "5.2.11", - "vue": "3.4.26", + "typescript": "5.6.2", + "uuid": "10.0.0", + "v-code-diff": "1.13.1", + "vite": "5.4.8", + "vue": "3.5.11", "vuedraggable": "next" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "1.0.0", "@misskey-dev/summaly": "5.1.0", - "@storybook/addon-actions": "8.0.9", - "@storybook/addon-essentials": "8.0.9", - "@storybook/addon-interactions": "8.0.9", - "@storybook/addon-links": "8.0.9", - "@storybook/addon-mdx-gfm": "8.0.9", - "@storybook/addon-storysource": "8.0.9", - "@storybook/blocks": "8.0.9", - "@storybook/components": "8.0.9", - "@storybook/core-events": "8.0.9", - "@storybook/manager-api": "8.0.9", - "@storybook/preview-api": "8.0.9", - "@storybook/react": "8.0.9", - "@storybook/react-vite": "8.0.9", - "@storybook/test": "8.0.9", - "@storybook/theming": "8.0.9", - "@storybook/types": "8.0.9", - "@storybook/vue3": "8.0.9", - "@storybook/vue3-vite": "8.0.9", - "@testing-library/vue": "8.0.3", - "@types/escape-regexp": "0.0.3", - "@types/estree": "1.0.5", - "@types/matter-js": "0.19.6", - "@types/micromatch": "4.0.7", - "@types/node": "20.12.7", + "@storybook/addon-actions": "8.3.4", + "@storybook/addon-essentials": "8.3.4", + "@storybook/addon-interactions": "8.3.4", + "@storybook/addon-links": "8.3.4", + "@storybook/addon-mdx-gfm": "8.3.4", + "@storybook/addon-storysource": "8.3.4", + "@storybook/blocks": "8.3.4", + "@storybook/components": "8.3.4", + "@storybook/core-events": "8.3.4", + "@storybook/manager-api": "8.3.4", + "@storybook/preview-api": "8.3.4", + "@storybook/react": "8.3.4", + "@storybook/react-vite": "8.3.4", + "@storybook/test": "8.3.4", + "@storybook/theming": "8.3.4", + "@storybook/types": "8.3.4", + "@storybook/vue3": "8.3.4", + "@storybook/vue3-vite": "8.3.4", + "@testing-library/vue": "8.1.0", + "@types/canvas-confetti": "^1.6.4", + "@types/estree": "1.0.6", + "@types/matter-js": "0.19.7", + "@types/micromatch": "4.0.9", + "@types/node": "20.14.12", "@types/punycode": "2.1.4", - "@types/sanitize-html": "2.11.0", + "@types/sanitize-html": "2.13.0", "@types/seedrandom": "3.0.8", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@types/uuid": "9.0.8", - "@types/ws": "8.5.10", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", - "@vitest/coverage-v8": "0.34.6", - "@vue/runtime-core": "3.4.26", - "acorn": "8.11.3", + "@types/uuid": "10.0.0", + "@types/ws": "8.5.12", + "@typescript-eslint/eslint-plugin": "7.17.0", + "@typescript-eslint/parser": "7.17.0", + "@vitest/coverage-v8": "1.6.0", + "@vue/runtime-core": "3.5.11", + "acorn": "8.12.1", "cross-env": "7.0.3", - "cypress": "13.8.1", - "eslint": "8.57.0", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-vue": "9.25.0", + "cypress": "13.15.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-vue": "9.28.0", "fast-glob": "3.3.2", "happy-dom": "10.0.3", "intersection-observer": "0.12.2", - "micromatch": "4.0.5", - "msw": "2.2.14", - "msw-storybook-addon": "2.0.1", - "nodemon": "3.1.0", - "prettier": "3.2.5", + "micromatch": "4.0.8", + "msw": "2.4.9", + "msw-storybook-addon": "2.0.3", + "nodemon": "3.1.7", + "prettier": "3.3.3", "react": "18.3.1", "react-dom": "18.3.1", "seedrandom": "3.0.5", - "start-server-and-test": "2.0.3", - "storybook": "8.0.9", + "start-server-and-test": "2.0.8", + "storybook": "8.3.4", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "vite-plugin-turbosnap": "1.0.3", - "vitest": "0.34.6", + "vitest": "1.6.0", "vitest-fetch-mock": "0.2.2", - "vue-component-type-helpers": "2.0.16", - "vue-eslint-parser": "9.4.2", - "vue-tsc": "2.0.16" + "vue-component-type-helpers": "2.1.6", + "vue-eslint-parser": "9.4.3", + "vue-tsc": "2.1.6" } } diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts index 875353f8a4..13a97e433c 100644 --- a/packages/frontend/src/_boot_.ts +++ b/packages/frontend/src/_boot_.ts @@ -6,6 +6,8 @@ // https://vitejs.dev/config/build-options.html#build-modulepreload import 'vite/modulepreload-polyfill'; +import '@tabler/icons-webfont/dist/tabler-icons.scss'; + import '@/style.scss'; import { mainBoot } from '@/boot/main-boot.js'; import { subBoot } from '@/boot/sub-boot.js'; diff --git a/packages/frontend/src/_dev_boot_.ts b/packages/frontend/src/_dev_boot_.ts index 7c6e537fbc..f312765dcf 100644 --- a/packages/frontend/src/_dev_boot_.ts +++ b/packages/frontend/src/_dev_boot_.ts @@ -3,11 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -// devモードで起動される際(index.htmlを使うとき)はrouterが暴発してしまってうまく読み込めない。 -// よって、devモードとして起動されるときはビルド時に組み込む形としておく。 -// (pnpm start時はpugファイルの中で静的リソースとして読み込むようになっており、この問題は起こっていない) -import '@tabler/icons-webfont/dist/tabler-icons.scss'; - await main(); import('@/_boot_.js'); @@ -48,7 +43,7 @@ async function main() { const theme = localStorage.getItem('theme'); if (theme) { for (const [k, v] of Object.entries(JSON.parse(theme))) { - document.documentElement.style.setProperty(`--${k}`, v.toString()); + document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString()); // HTMLの theme-color 適用 if (k === 'htmlThemeColor') { diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index f99b550a83..b91834b94f 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -8,9 +8,9 @@ import * as Misskey from 'misskey-js'; import { showSuspendedDialog } from '@/scripts/show-suspended-dialog.js'; import { i18n } from '@/i18n.js'; import { miLocalStorage } from '@/local-storage.js'; -import { MenuButton } from '@/types/menu.js'; +import type { MenuItem, MenuButton } from '@/types/menu.js'; import { del, get, set } from '@/scripts/idb-proxy.js'; -import { apiUrl } from '@/config.js'; +import { apiUrl } from '@@/js/config.js'; import { waiting, popup, popupMenu, success, alert } from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { unisonReload, reloadChannel } from '@/scripts/unison-reload.js'; @@ -184,10 +184,12 @@ export async function refreshAccount() { export async function login(token: Account['token'], redirect?: string) { const showing = ref(true); - popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { success: false, showing: showing, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); if (_DEV_) console.log('logging as token ', token); const me = await fetchAccount(token, undefined, true) .catch(reason => { @@ -223,21 +225,23 @@ export async function openAccountMenu(opts: { if (!$i) return; function showSigninDialog() { - popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { - done: res => { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { + done: (res: Misskey.entities.SigninFlowResponse & { finished: true }) => { addAccount(res.id, res.i); success(); }, - }, 'closed'); + closed: () => dispose(), + }); } function createAccount() { - popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { - done: res => { - addAccount(res.id, res.i); - switchAccountWithToken(res.i); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { + done: (res: Misskey.entities.SignupResponse) => { + addAccount(res.id, res.token); + switchAccountWithToken(res.token); }, - }, 'closed'); + closed: () => dispose(), + }); } async function switchAccount(account: Misskey.entities.UserDetailed) { @@ -284,14 +288,26 @@ export async function openAccountMenu(opts: { }); })); + const menuItems: MenuItem[] = []; + if (opts.withExtraOperation) { - popupMenu([...[{ - type: 'link' as const, + menuItems.push({ + type: 'link', text: i18n.ts.profile, - to: `/@${ $i.username }`, + to: `/@${$i.username}`, avatar: $i, - }, { type: 'divider' as const }, ...(opts.includeCurrentAccount ? [createItem($i)] : []), ...accountItemPromises, { - type: 'parent' as const, + }, { + type: 'divider', + }); + + if (opts.includeCurrentAccount) { + menuItems.push(createItem($i)); + } + + menuItems.push(...accountItemPromises); + + menuItems.push({ + type: 'parent', icon: 'ti ti-plus', text: i18n.ts.addAccount, children: [{ @@ -302,18 +318,22 @@ export async function openAccountMenu(opts: { action: () => { createAccount(); }, }], }, { - type: 'link' as const, + type: 'link', icon: 'ti ti-users', text: i18n.ts.manageAccounts, to: '/settings/accounts', - }]], ev.currentTarget ?? ev.target, { - align: 'left', }); } else { - popupMenu([...(opts.includeCurrentAccount ? [createItem($i)] : []), ...accountItemPromises], ev.currentTarget ?? ev.target, { - align: 'left', - }); + if (opts.includeCurrentAccount) { + menuItems.push(createItem($i)); + } + + menuItems.push(...accountItemPromises); } + + popupMenu(menuItems, ev.currentTarget ?? ev.target, { + align: 'left', + }); } if (_DEV_) { diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index d86ae18ffe..1145891b71 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -5,10 +5,10 @@ import { computed, watch, version as vueVersion, App } from 'vue'; import { compareVersions } from 'compare-versions'; +import { version, lang, updateLocale, locale } from '@@/js/config.js'; import widgets from '@/widgets/index.js'; import directives from '@/directives/index.js'; import components from '@/components/index.js'; -import { version, lang, updateLocale, locale } from '@/config.js'; import { applyTheme } from '@/scripts/theme.js'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js'; import { updateI18n } from '@/i18n.js'; @@ -22,7 +22,8 @@ import { getAccountFromId } from '@/scripts/get-account-from-id.js'; import { deckStore } from '@/ui/deck/deck-store.js'; import { miLocalStorage } from '@/local-storage.js'; import { fetchCustomEmojis } from '@/custom-emojis.js'; -import { setupRouter } from '@/router/definition.js'; +import { setupRouter } from '@/router/main.js'; +import { createMainRouter } from '@/router/definition.js'; export async function common(createVue: () => App) { console.info(`Misskey v${version}`); @@ -145,10 +146,9 @@ export async function common(createVue: () => App) { // NOTE: この処理は必ずクライアント更新チェック処理より後に来ること(テーマ再構築のため) watch(defaultStore.reactiveState.darkMode, (darkMode) => { applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')); - document.documentElement.dataset.colorMode = darkMode ? 'dark' : 'light'; }, { immediate: miLocalStorage.getItem('theme') == null }); - document.documentElement.dataset.colorMode = defaultStore.state.darkMode ? 'dark' : 'light'; + document.documentElement.dataset.colorScheme = defaultStore.state.darkMode ? 'dark' : 'light'; const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); @@ -182,24 +182,18 @@ export async function common(createVue: () => App) { if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON.parse(instance.defaultLightTheme)); if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON.parse(instance.defaultDarkTheme)); defaultStore.set('themeInitial', false); - } else { - if (defaultStore.state.darkMode) { - applyTheme(darkTheme.value); - } else { - applyTheme(lightTheme.value); - } } }); watch(defaultStore.reactiveState.useBlurEffectForModal, v => { - document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none'); + document.documentElement.style.setProperty('--MI-modalBgFilter', v ? 'blur(4px)' : 'none'); }, { immediate: true }); watch(defaultStore.reactiveState.useBlurEffect, v => { if (v) { - document.documentElement.style.removeProperty('--blur'); + document.documentElement.style.removeProperty('--MI-blur'); } else { - document.documentElement.style.setProperty('--blur', 'none'); + document.documentElement.style.setProperty('--MI-blur', 'none'); } }, { immediate: true }); @@ -239,7 +233,7 @@ export async function common(createVue: () => App) { const app = createVue(); - setupRouter(app); + setupRouter(app, createMainRouter); if (_DEV_) { app.config.performance = true; diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 5cb19f388a..76459ab330 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -5,7 +5,8 @@ import { createApp, defineAsyncComponent, markRaw } from 'vue'; import { common } from './common.js'; -import { ui } from '@/config.js'; +import type * as Misskey from 'misskey-js'; +import { ui } from '@@/js/config.js'; import { i18n } from '@/i18n.js'; import { alert, confirm, popup, post, toast } from '@/os.js'; import { useStream } from '@/stream.js'; @@ -13,7 +14,6 @@ import * as sound from '@/scripts/sound.js'; import { $i, signout, updateAccount } from '@/account.js'; import { instance } from '@/instance.js'; import { ColdDeviceStorage, defaultStore } from '@/store.js'; -import { makeHotkey } from '@/scripts/hotkey.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; import { miLocalStorage } from '@/local-storage.js'; import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js'; @@ -21,6 +21,8 @@ import { initializeSw } from '@/scripts/initialize-sw.js'; import { deckStore } from '@/ui/deck/deck-store.js'; import { emojiPicker } from '@/scripts/emoji-picker.js'; import { mainRouter } from '@/router/main.js'; +import { type Keymap, makeHotkey } from '@/scripts/hotkey.js'; +import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js'; export async function mainBoot() { const { isClientUpdated } = await common(() => createApp( @@ -35,7 +37,9 @@ export async function mainBoot() { emojiPicker.init(); if (isClientUpdated && $i) { - popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, { + closed: () => dispose(), + }); } const stream = useStream(); @@ -59,6 +63,18 @@ export async function mainBoot() { } }); + stream.on('emojiAdded', emojiData => { + addCustomEmoji(emojiData.emoji); + }); + + stream.on('emojiUpdated', emojiData => { + updateCustomEmojis(emojiData.emojis); + }); + + stream.on('emojiDeleted', emojiData => { + removeCustomEmojis(emojiData.emojis); + }); + for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) { import('@/plugin.js').then(async ({ install }) => { // Workaround for https://bugs.webkit.org/show_bug.cgi?id=242740 @@ -67,14 +83,6 @@ export async function mainBoot() { }); } - const hotkeys = { - 'd': (): void => { - defaultStore.set('darkMode', !defaultStore.state.darkMode); - }, - 's': (): void => { - mainRouter.push('/search'); - }, - }; try { if (defaultStore.state.enableSeasonalScreenEffect) { const month = new Date().getMonth() + 1; @@ -96,36 +104,41 @@ export async function mainBoot() { }).render(); } } - } + } } catch (error) { // console.error(error); console.error('Failed to initialise the seasonal screen effect canvas context:', error); } if ($i) { - // only add post shortcuts if logged in - hotkeys['p|n'] = post; - defaultStore.loaded.then(() => { if (defaultStore.state.accountSetupWizard !== -1) { - popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, { + closed: () => dispose(), + }); } }); for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } - stream.on('announcementCreated', (ev) => { + function onAnnouncementCreated (ev: { announcement: Misskey.entities.Announcement }) { const announcement = ev.announcement; if (announcement.display === 'dialog') { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } - }); + } + + stream.on('announcementCreated', onAnnouncementCreated); if ($i.isDeleted) { alert({ @@ -217,43 +230,54 @@ export async function mainBoot() { claimAchievement('collectAchievements30'); } - window.setInterval(() => { - if (Math.floor(Math.random() * 20000) === 0) { - claimAchievement('justPlainLucky'); - } - }, 1000 * 10); - - window.setTimeout(() => { - claimAchievement('client30min'); - }, 1000 * 60 * 30); - - window.setTimeout(() => { - claimAchievement('client60min'); - }, 1000 * 60 * 60); - - const lastUsed = miLocalStorage.getItem('lastUsed'); - if (lastUsed) { - const lastUsedDate = parseInt(lastUsed, 10); - // 二時間以上前なら - if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) { - toast(i18n.tsx.welcomeBackWithName({ - name: $i.name || $i.username, - })); - } + if (!claimedAchievements.includes('justPlainLucky')) { + window.setInterval(() => { + if (Math.floor(Math.random() * 20000) === 0) { + claimAchievement('justPlainLucky'); + } + }, 1000 * 10); } - miLocalStorage.setItem('lastUsed', Date.now().toString()); + + if (!claimedAchievements.includes('client30min')) { + window.setTimeout(() => { + claimAchievement('client30min'); + }, 1000 * 60 * 30); + } + + if (!claimedAchievements.includes('client60min')) { + window.setTimeout(() => { + claimAchievement('client60min'); + }, 1000 * 60 * 60); + } + + // 邪魔 + //const lastUsed = miLocalStorage.getItem('lastUsed'); + //if (lastUsed) { + // const lastUsedDate = parseInt(lastUsed, 10); + // // 二時間以上前なら + // if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) { + // toast(i18n.tsx.welcomeBackWithName({ + // name: $i.name || $i.username, + // })); + // } + //} + //miLocalStorage.setItem('lastUsed', Date.now().toString()); const latestDonationInfoShownAt = miLocalStorage.getItem('latestDonationInfoShownAt'); const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo'); if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) { if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) { - popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, { + closed: () => dispose(), + }); } } const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read'); if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') { - popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, { + closed: () => dispose(), + }); } if ('Notification' in window) { @@ -314,6 +338,9 @@ export async function mainBoot() { updateAccount({ hasUnreadAnnouncement: false }); }); + // 個人宛てお知らせが発行されたとき + main.on('announcementCreated', onAnnouncementCreated); + // トークンが再生成されたとき // このままではMisskeyが利用できないので強制的にサインアウトさせる main.on('myTokenRegenerated', () => { @@ -322,7 +349,19 @@ export async function mainBoot() { } // shortcut - document.addEventListener('keydown', makeHotkey(hotkeys)); + const keymap = { + 'p|n': () => { + if ($i == null) return; + post(); + }, + 'd': () => { + defaultStore.set('darkMode', !defaultStore.state.darkMode); + }, + 's': () => { + mainRouter.push('/search'); + }, + } as const satisfies Keymap; + document.addEventListener('keydown', makeHotkey(keymap), { passive: false }); initializeSw(); } diff --git a/packages/frontend/src/boot/sub-boot.ts b/packages/frontend/src/boot/sub-boot.ts index 017457822b..35c84d5568 100644 --- a/packages/frontend/src/boot/sub-boot.ts +++ b/packages/frontend/src/boot/sub-boot.ts @@ -5,9 +5,12 @@ import { createApp, defineAsyncComponent } from 'vue'; import { common } from './common.js'; +import { emojiPicker } from '@/scripts/emoji-picker.js'; export async function subBoot() { const { isClientUpdated } = await common(() => createApp( defineAsyncComponent(() => import('@/ui/minimum.vue')), )); + + emojiPicker.init(); } diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue index a28e7c2559..b9413270ae 100644 --- a/packages/frontend/src/components/MkAbuseReport.vue +++ b/packages/frontend/src/components/MkAbuseReport.vue @@ -4,112 +4,153 @@ SPDX-License-Identifier: AGPL-3.0-only --> - diff --git a/packages/frontend/src/components/MkAbuseReportWindow.vue b/packages/frontend/src/components/MkAbuseReportWindow.vue index b09c7bb3fb..a634a748e9 100644 --- a/packages/frontend/src/components/MkAbuseReportWindow.vue +++ b/packages/frontend/src/components/MkAbuseReportWindow.vue @@ -39,7 +39,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; const props = defineProps<{ - user: Misskey.entities.UserDetailed; + user: Misskey.entities.UserLite; initialComment?: string; }>(); diff --git a/packages/frontend/src/components/MkAccountMoved.vue b/packages/frontend/src/components/MkAccountMoved.vue index 6c0774b634..0839955d9d 100644 --- a/packages/frontend/src/components/MkAccountMoved.vue +++ b/packages/frontend/src/components/MkAccountMoved.vue @@ -16,7 +16,7 @@ import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import MkMention from './MkMention.vue'; import { i18n } from '@/i18n.js'; -import { host as localHost } from '@/config.js'; +import { host as localHost } from '@@/js/config.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; const user = ref(); @@ -32,9 +32,9 @@ misskeyApi('users/show', { userId: props.movedTo }).then(u => user.value = u); .root { padding: 16px; font-size: 90%; - background: var(--infoWarnBg); - color: var(--error); - border-radius: var(--radius); + background: var(--MI_THEME-infoWarnBg); + color: var(--MI_THEME-error); + border-radius: var(--MI-radius); } .link { diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue index 5d103fa789..c8134416b5 100644 --- a/packages/frontend/src/components/MkAchievements.vue +++ b/packages/frontend/src/components/MkAchievements.vue @@ -153,7 +153,7 @@ onMounted(() => { background: linear-gradient(0deg, #ffee20, #eb7018); } - &:before { + &::before { content: ""; display: block; position: absolute; @@ -173,7 +173,7 @@ onMounted(() => { background: linear-gradient(0deg, #e1e1e1, #7c7c7c); } - &:before { + &::before { content: ""; display: block; position: absolute; diff --git a/packages/frontend/src/components/MkAnalogClock.vue b/packages/frontend/src/components/MkAnalogClock.vue index 835efbd6cd..c8fa6246e0 100644 --- a/packages/frontend/src/components/MkAnalogClock.vue +++ b/packages/frontend/src/components/MkAnalogClock.vue @@ -193,12 +193,12 @@ tick(); function calcColors() { const computedStyle = getComputedStyle(document.documentElement); - const dark = tinycolor(computedStyle.getPropertyValue('--bg')).isDark(); - const accent = tinycolor(computedStyle.getPropertyValue('--accent')).toHexString(); + const dark = tinycolor(computedStyle.getPropertyValue('--MI_THEME-bg')).isDark(); + const accent = tinycolor(computedStyle.getPropertyValue('--MI_THEME-accent')).toHexString(); majorGraduationColor.value = dark ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)'; //minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'; sHandColor.value = dark ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.3)'; - mHandColor.value = tinycolor(computedStyle.getPropertyValue('--fg')).toHexString(); + mHandColor.value = tinycolor(computedStyle.getPropertyValue('--MI_THEME-fg')).toHexString(); hHandColor.value = accent; nowColor.value = accent; } diff --git a/packages/frontend/src/components/MkAnnouncementDialog.vue b/packages/frontend/src/components/MkAnnouncementDialog.vue index f27694658e..1adb244c9e 100644 --- a/packages/frontend/src/components/MkAnnouncementDialog.vue +++ b/packages/frontend/src/components/MkAnnouncementDialog.vue @@ -9,9 +9,9 @@ SPDX-License-Identifier: AGPL-3.0-only
- - - + + + {{ announcement.title }}
@@ -83,8 +83,8 @@ onMounted(() => { min-width: 320px; max-width: 480px; box-sizing: border-box; - background: var(--panel); - border-radius: var(--radius); + background: var(--MI_THEME-panel); + border-radius: var(--MI-radius); } .header { diff --git a/packages/frontend/src/components/MkAntennaEditor.stories.impl.ts b/packages/frontend/src/components/MkAntennaEditor.stories.impl.ts new file mode 100644 index 0000000000..1749e07a4e --- /dev/null +++ b/packages/frontend/src/components/MkAntennaEditor.stories.impl.ts @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { action } from '@storybook/addon-actions'; +import { StoryObj } from '@storybook/vue3'; +import { HttpResponse, http } from 'msw'; +import { commonHandlers } from '../../.storybook/mocks.js'; +import MkAntennaEditor from './MkAntennaEditor.vue'; +export const Default = { + render(args) { + return { + components: { + MkAntennaEditor, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...this.args, + }; + }, + events() { + return { + created: action('created'), + updated: action('updated'), + deleted: action('deleted'), + }; + }, + }, + template: '', + }; + }, + args: { + }, + parameters: { + layout: 'fullscreen', + msw: { + handlers: [ + ...commonHandlers, + http.post('/api/antennas/create', async ({ request }) => { + action('POST /api/antennas/create')(await request.json()); + return HttpResponse.json({}); + }), + http.post('/api/antennas/update', async ({ request }) => { + action('POST /api/antennas/update')(await request.json()); + return HttpResponse.json({}); + }), + http.post('/api/antennas/delete', async ({ request }) => { + action('POST /api/antennas/delete')(await request.json()); + return HttpResponse.json(); + }), + ], + }, + }, +} satisfies StoryObj; diff --git a/packages/frontend/src/pages/my-antennas/editor.vue b/packages/frontend/src/components/MkAntennaEditor.vue similarity index 63% rename from packages/frontend/src/pages/my-antennas/editor.vue rename to packages/frontend/src/components/MkAntennaEditor.vue index 2949bfc02c..2386ba6fa7 100644 --- a/packages/frontend/src/pages/my-antennas/editor.vue +++ b/packages/frontend/src/components/MkAntennaEditor.vue @@ -41,8 +41,10 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.withFileAntenna }}
- {{ i18n.ts.save }} - {{ i18n.ts.delete }} +
+ {{ i18n.ts.save }} + {{ i18n.ts.delete }} +
@@ -59,28 +61,53 @@ import MkSwitch from '@/components/MkSwitch.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { i18n } from '@/i18n.js'; +import { deepMerge } from '@/scripts/merge.js'; +import type { DeepPartial } from '@/scripts/merge.js'; + +type PartialAllowedAntenna = Omit & { + id?: string; + createdAt?: string; + updatedAt?: string; +}; const props = defineProps<{ - antenna: Misskey.entities.Antenna + antenna?: DeepPartial; }>(); +const initialAntenna = deepMerge(props.antenna ?? {}, { + name: '', + src: 'all', + userListId: null, + users: [], + keywords: [], + excludeKeywords: [], + excludeBots: false, + withReplies: false, + caseSensitive: false, + localOnly: false, + withFile: false, + isActive: true, + hasUnreadNote: false, + notify: false, +}); + const emit = defineEmits<{ - (ev: 'created'): void, - (ev: 'updated'): void, + (ev: 'created', newAntenna: Misskey.entities.Antenna): void, + (ev: 'updated', editedAntenna: Misskey.entities.Antenna): void, (ev: 'deleted'): void, }>(); -const name = ref(props.antenna.name); -const src = ref(props.antenna.src); -const userListId = ref(props.antenna.userListId); -const users = ref(props.antenna.users.join('\n')); -const keywords = ref(props.antenna.keywords.map(x => x.join(' ')).join('\n')); -const excludeKeywords = ref(props.antenna.excludeKeywords.map(x => x.join(' ')).join('\n')); -const caseSensitive = ref(props.antenna.caseSensitive); -const localOnly = ref(props.antenna.localOnly); -const excludeBots = ref(props.antenna.excludeBots); -const withReplies = ref(props.antenna.withReplies); -const withFile = ref(props.antenna.withFile); +const name = ref(initialAntenna.name); +const src = ref(initialAntenna.src); +const userListId = ref(initialAntenna.userListId); +const users = ref(initialAntenna.users.join('\n')); +const keywords = ref(initialAntenna.keywords.map(x => x.join(' ')).join('\n')); +const excludeKeywords = ref(initialAntenna.excludeKeywords.map(x => x.join(' ')).join('\n')); +const caseSensitive = ref(initialAntenna.caseSensitive); +const localOnly = ref(initialAntenna.localOnly); +const excludeBots = ref(initialAntenna.excludeBots); +const withReplies = ref(initialAntenna.withReplies); +const withFile = ref(initialAntenna.withFile); const userLists = ref(null); watch(() => src.value, async () => { @@ -104,24 +131,26 @@ async function saveAntenna() { excludeKeywords: excludeKeywords.value.trim().split('\n').map(x => x.trim().split(' ')), }; - if (props.antenna.id == null) { - await os.apiWithDialog('antennas/create', antennaData); - emit('created'); + if (initialAntenna.id == null) { + const res = await os.apiWithDialog('antennas/create', antennaData); + emit('created', res); } else { - await os.apiWithDialog('antennas/update', { ...antennaData, antennaId: props.antenna.id }); - emit('updated'); + const res = await os.apiWithDialog('antennas/update', { ...antennaData, antennaId: initialAntenna.id }); + emit('updated', res); } } async function deleteAntenna() { + if (initialAntenna.id == null) return; + const { canceled } = await os.confirm({ type: 'warning', - text: i18n.tsx.removeAreYouSure({ x: props.antenna.name }), + text: i18n.tsx.removeAreYouSure({ x: initialAntenna.name }), }); if (canceled) return; await misskeyApi('antennas/delete', { - antennaId: props.antenna.id, + antennaId: initialAntenna.id, }); os.success(); @@ -141,6 +170,6 @@ function addUser() { .actions { margin-top: 16px; padding: 24px 0; - border-top: solid 0.5px var(--divider); + border-top: solid 0.5px var(--MI_THEME-divider); } diff --git a/packages/frontend/src/components/MkAntennaEditorDialog.stories.impl.ts b/packages/frontend/src/components/MkAntennaEditorDialog.stories.impl.ts new file mode 100644 index 0000000000..1c6ca83b47 --- /dev/null +++ b/packages/frontend/src/components/MkAntennaEditorDialog.stories.impl.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { action } from '@storybook/addon-actions'; +import { StoryObj } from '@storybook/vue3'; +import { HttpResponse, http } from 'msw'; +import { commonHandlers } from '../../.storybook/mocks.js'; +import MkAntennaEditorDialog from './MkAntennaEditorDialog.vue'; +export const Default = { + render(args) { + return { + components: { + MkAntennaEditorDialog, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...this.args, + }; + }, + events() { + return { + created: action('created'), + updated: action('updated'), + deleted: action('deleted'), + closed: action('closed'), + }; + }, + }, + template: '', + }; + }, + args: { + }, + parameters: { + layout: 'centered', + msw: { + handlers: [ + ...commonHandlers, + http.post('/api/antennas/create', async ({ request }) => { + action('POST /api/antennas/create')(await request.json()); + return HttpResponse.json({}); + }), + http.post('/api/antennas/update', async ({ request }) => { + action('POST /api/antennas/update')(await request.json()); + return HttpResponse.json({}); + }), + http.post('/api/antennas/delete', async ({ request }) => { + action('POST /api/antennas/delete')(await request.json()); + return HttpResponse.json(); + }), + ], + }, + }, +} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkAntennaEditorDialog.vue b/packages/frontend/src/components/MkAntennaEditorDialog.vue new file mode 100644 index 0000000000..6d815d29f3 --- /dev/null +++ b/packages/frontend/src/components/MkAntennaEditorDialog.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/packages/frontend/src/components/MkAsUi.vue b/packages/frontend/src/components/MkAsUi.vue index 18e8e7542e..e52ab5ccad 100644 --- a/packages/frontend/src/components/MkAsUi.vue +++ b/packages/frontend/src/components/MkAsUi.vue @@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only -
+
@@ -63,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/components/MkDonation.stories.impl.ts b/packages/frontend/src/components/MkDonation.stories.impl.ts new file mode 100644 index 0000000000..27d6b7df6c --- /dev/null +++ b/packages/frontend/src/components/MkDonation.stories.impl.ts @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { action } from '@storybook/addon-actions'; +import { StoryObj } from '@storybook/vue3'; +import { onBeforeUnmount } from 'vue'; +import MkDonation from './MkDonation.vue'; +import { instance } from '@/instance.js'; +export const Default = { + render(args) { + return { + components: { + MkDonation, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...this.args, + }; + }, + events() { + return { + closed: action('closed'), + }; + }, + }, + template: '', + }; + }, + args: { + // @ts-expect-error name is used for mocking instance + name: 'Misskey Hub', + }, + decorators: [ + (_, { args }) => ({ + setup() { + // @ts-expect-error name is used for mocking instance + instance.name = args.name; + onBeforeUnmount(() => instance.name = null); + }, + template: '', + }), + ], + parameters: { + layout: 'centered', + }, +} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkDonation.vue b/packages/frontend/src/components/MkDonation.vue index 434fc81582..0e0da64750 100644 --- a/packages/frontend/src/components/MkDonation.vue +++ b/packages/frontend/src/components/MkDonation.vue @@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts b/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts new file mode 100644 index 0000000000..69aef577de --- /dev/null +++ b/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import MkEmojiPicker_section from './MkEmojiPicker.section.vue'; +void MkEmojiPicker_section; diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue index c13164c296..f4caa730bf 100644 --- a/packages/frontend/src/components/MkEmojiPicker.section.vue +++ b/packages/frontend/src/components/MkEmojiPicker.section.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only + diff --git a/packages/frontend/src/pages/flash/flash-index.vue b/packages/frontend/src/pages/flash/flash-index.vue index f63a799365..2b85489706 100644 --- a/packages/frontend/src/pages/flash/flash-index.vue +++ b/packages/frontend/src/pages/flash/flash-index.vue @@ -55,7 +55,8 @@ const tab = ref('featured'); const featuredFlashsPagination = { endpoint: 'flash/featured' as const, - noPaging: true, + limit: 5, + offsetMode: true, }; const myFlashsPagination = { endpoint: 'flash/my' as const, diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index 40499fde0e..3b982a405e 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ flash.likedCount }} +
@@ -50,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.createdAt }}:
- {{ i18n.ts._play.editThisPage }} + {{ i18n.ts._play.editThisPage }} @@ -61,13 +62,13 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/gallery/edit.vue b/packages/frontend/src/pages/gallery/edit.vue index a68a7e5c41..70f8b2c31d 100644 --- a/packages/frontend/src/pages/gallery/edit.vue +++ b/packages/frontend/src/pages/gallery/edit.vue @@ -141,7 +141,7 @@ definePageMetadata(() => ({ top: 8px; left: 9px; padding: 8px; - background: var(--panel); + background: var(--MI_THEME-panel); } > .remove { @@ -149,7 +149,7 @@ definePageMetadata(() => ({ top: 8px; right: 9px; padding: 8px; - background: var(--panel); + background: var(--MI_THEME-panel); } } diff --git a/packages/frontend/src/pages/gallery/index.vue b/packages/frontend/src/pages/gallery/index.vue index e0e187f2ce..f396fd2c0c 100644 --- a/packages/frontend/src/pages/gallery/index.vue +++ b/packages/frontend/src/pages/gallery/index.vue @@ -130,6 +130,6 @@ definePageMetadata(() => ({ display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); grid-gap: 12px; - margin: 0 var(--margin); + margin: 0 var(--MI-margin); } diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue index 615675225d..feb4c60611 100644 --- a/packages/frontend/src/pages/gallery/post.vue +++ b/packages/frontend/src/pages/gallery/post.vue @@ -31,6 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only +
@@ -62,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/pages/install-extensions.vue b/packages/frontend/src/pages/install-extensions.vue index 4bee437f65..6d68ed83b4 100644 --- a/packages/frontend/src/pages/install-extensions.vue +++ b/packages/frontend/src/pages/install-extensions.vue @@ -8,76 +8,26 @@ SPDX-License-Identifier: AGPL-3.0-only -
-
- - - -
-

{{ i18n.ts._externalResourceInstaller[`_${data.type}`].title }}

-
{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}
- {{ i18n.ts._plugin.installWarn }} - - -
- + + +
@@ -96,14 +46,11 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue index 97f32d35cd..448244204d 100644 --- a/packages/frontend/src/pages/note.vue +++ b/packages/frontend/src/pages/note.vue @@ -170,11 +170,11 @@ definePageMetadata(() => ({ } .loadNext { - margin-bottom: var(--margin); + margin-bottom: var(--MI-margin); } .loadPrev { - margin-top: var(--margin); + margin-top: var(--MI-margin); } .loadButton { @@ -182,7 +182,7 @@ definePageMetadata(() => ({ } .note { - border-radius: var(--radius); - background: var(--panel); + border-radius: var(--MI-radius); + background: var(--MI_THEME-panel); } diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue index 28f5838296..46ee501c76 100644 --- a/packages/frontend/src/pages/notifications.vue +++ b/packages/frontend/src/pages/notifications.vue @@ -30,7 +30,7 @@ import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; -import { notificationTypes } from '@/const.js'; +import { notificationTypes } from '@@/js/const.js'; const tab = ref('all'); const includeTypes = ref(null); @@ -102,7 +102,7 @@ definePageMetadata(() => ({ diff --git a/packages/frontend/src/pages/page-editor/common.ts b/packages/frontend/src/pages/page-editor/common.ts new file mode 100644 index 0000000000..420c8fc967 --- /dev/null +++ b/packages/frontend/src/pages/page-editor/common.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { i18n } from '@/i18n.js'; + +export function getPageBlockList() { + return [ + { value: 'section', text: i18n.ts._pages.blocks.section }, + { value: 'text', text: i18n.ts._pages.blocks.text }, + { value: 'image', text: i18n.ts._pages.blocks.image }, + { value: 'note', text: i18n.ts._pages.blocks.note }, + ]; +} diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue index 47e9c08c2c..0f8dc33143 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue @@ -29,6 +29,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { deepClone } from '@/scripts/clone.js'; import MkButton from '@/components/MkButton.vue'; +import { getPageBlockList } from '@/pages/page-editor/common.js'; const XBlocks = defineAsyncComponent(() => import('../page-editor.blocks.vue')); @@ -53,11 +54,9 @@ watch(children, () => { deep: true, }); -const getPageBlockList = inject<(any) => any>('getPageBlockList'); - async function rename() { const { canceled, result: title } = await os.inputText({ - title: 'Enter title', + title: i18n.ts._pages.enterSectionTitle, default: props.modelValue.title, }); if (canceled) return; diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue index 14c3e6845e..f09f7e1acd 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue @@ -63,7 +63,7 @@ onUnmounted(() => { box-shadow: none; padding: 16px; background: transparent; - color: var(--fg); + color: var(--MI_THEME-fg); font-size: 14px; box-sizing: border-box; } diff --git a/packages/frontend/src/pages/page-editor/page-editor.container.vue b/packages/frontend/src/pages/page-editor/page-editor.container.vue index f2081c452c..a96c2c2a77 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.container.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.container.vue @@ -60,12 +60,12 @@ function remove() { .cpjygsrt { position: relative; overflow: hidden; - background: var(--panel); - border: solid 2px var(--X12); + background: var(--MI_THEME-panel); + border: solid 2px var(--MI_THEME-X12); border-radius: 8px; &:hover { - border: solid 2px var(--X13); + border: solid 2px var(--MI_THEME-X13); } &.warn { diff --git a/packages/frontend/src/pages/page-editor/page-editor.vue b/packages/frontend/src/pages/page-editor/page-editor.vue index af32fd2274..ddb808390c 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.vue @@ -69,7 +69,7 @@ import MkButton from '@/components/MkButton.vue'; import MkSelect from '@/components/MkSelect.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import MkInput from '@/components/MkInput.vue'; -import { url } from '@/config.js'; +import { url } from '@@/js/config.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { selectFile } from '@/scripts/select-file.js'; @@ -77,6 +77,7 @@ import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import { $i } from '@/account.js'; import { mainRouter } from '@/router/main.js'; +import { getPageBlockList } from '@/pages/page-editor/common.js'; const props = defineProps<{ initPageId?: string; @@ -101,7 +102,6 @@ const alignCenter = ref(false); const hideTitleWhenPinned = ref(false); provide('readonly', readonly.value); -provide('getPageBlockList', getPageBlockList); watch(eyeCatchingImageId, async () => { if (eyeCatchingImageId.value == null) { @@ -216,15 +216,6 @@ async function add() { content.value.push({ id, type }); } -function getPageBlockList() { - return [ - { value: 'section', text: i18n.ts._pages.blocks.section }, - { value: 'text', text: i18n.ts._pages.blocks.text }, - { value: 'image', text: i18n.ts._pages.blocks.image }, - { value: 'note', text: i18n.ts._pages.blocks.note }, - ]; -} - function setEyeCatchingImage(img) { selectFile(img.currentTarget ?? img.target, null).then(file => { eyeCatchingImageId.value = file.id; diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index e73d032000..a1bec52f18 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -62,8 +62,10 @@ SPDX-License-Identifier: AGPL-3.0-only {{ page.likedCount }}
+ +
@@ -78,14 +80,6 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.createdAt }}:
{{ i18n.ts.updatedAt }}:
-
- {{ i18n.ts._pages.viewSource }} - -
@@ -104,13 +98,13 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/reset-password.vue b/packages/frontend/src/pages/reset-password.vue index 6b67a9cc87..6d24029535 100644 --- a/packages/frontend/src/pages/reset-password.vue +++ b/packages/frontend/src/pages/reset-password.vue @@ -44,7 +44,9 @@ async function save() { onMounted(() => { if (props.token == null) { - os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {}, 'closed'); + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, { + closed: () => dispose(), + }); mainRouter.push('/'); } }); diff --git a/packages/frontend/src/pages/reversi/game.board.vue b/packages/frontend/src/pages/reversi/game.board.vue index 7d9cefa5c9..429f502133 100644 --- a/packages/frontend/src/pages/reversi/game.board.vue +++ b/packages/frontend/src/pages/reversi/game.board.vue @@ -149,9 +149,9 @@ import MkButton from '@/components/MkButton.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import { deepClone } from '@/scripts/clone.js'; -import { useInterval } from '@/scripts/use-interval.js'; +import { useInterval } from '@@/js/use-interval.js'; import { signinRequired } from '@/account.js'; -import { url } from '@/config.js'; +import { url } from '@@/js/config.js'; import { i18n } from '@/i18n.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { userPage } from '@/filters/user.js'; @@ -504,7 +504,7 @@ $gap: 4px; .boardInner { padding: 32px; - background: var(--panel); + background: var(--MI_THEME-panel); box-shadow: 0 0 2px 1px #ce8a5c, inset 0 0 1px 1px #693410; border-radius: 8px; } @@ -574,34 +574,34 @@ $gap: 4px; transition: border 0.25s ease, opacity 0.25s ease; &.boardCell_empty { - border: solid 2px var(--divider); + border: solid 2px var(--MI_THEME-divider); } &.boardCell_empty.boardCell_can { - border-color: var(--accent); + border-color: var(--MI_THEME-accent); opacity: 0.5; } &.boardCell_empty.boardCell_myTurn { - border-color: var(--divider); + border-color: var(--MI_THEME-divider); opacity: 1; &.boardCell_can { - border-color: var(--accent); + border-color: var(--MI_THEME-accent); cursor: pointer; &:hover { - background: var(--accent); + background: var(--MI_THEME-accent); } } } &.boardCell_prev { - box-shadow: 0 0 0 4px var(--accent); + box-shadow: 0 0 0 4px var(--MI_THEME-accent); } &.boardCell_isEnded { - border-color: var(--divider); + border-color: var(--MI_THEME-divider); } &.boardCell_none { diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue index 31c0003130..dfb6e3f53e 100644 --- a/packages/frontend/src/pages/reversi/game.setting.vue +++ b/packages/frontend/src/pages/reversi/game.setting.vue @@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -449,7 +445,7 @@ definePageMetadata(() => ({ diff --git a/packages/frontend/src/pages/settings/sounds.vue b/packages/frontend/src/pages/settings/sounds.vue index 090f0cf14c..9fcf564e55 100644 --- a/packages/frontend/src/pages/settings/sounds.vue +++ b/packages/frontend/src/pages/settings/sounds.vue @@ -21,8 +21,14 @@ SPDX-License-Identifier: AGPL-3.0-only - - + + + +
@@ -54,8 +60,6 @@ const sounds = ref>>({ note: defaultStore.reactiveState.sound_note, noteMy: defaultStore.reactiveState.sound_noteMy, notification: defaultStore.reactiveState.sound_notification, - antenna: defaultStore.reactiveState.sound_antenna, - channel: defaultStore.reactiveState.sound_channel, reaction: defaultStore.reactiveState.sound_reaction, }); diff --git a/packages/frontend/src/pages/settings/statusbar.statusbar.vue b/packages/frontend/src/pages/settings/statusbar.statusbar.vue index 92e389a288..67943524ef 100644 --- a/packages/frontend/src/pages/settings/statusbar.statusbar.vue +++ b/packages/frontend/src/pages/settings/statusbar.statusbar.vue @@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only