summaryrefslogtreecommitdiff
path: root/packages/backend/src
diff options
context:
space:
mode:
authormisskey-release-bot[bot] <157398866+misskey-release-bot[bot]@users.noreply.github.com>2025-01-28 12:29:14 +0000
committerGitHub <noreply@github.com>2025-01-28 12:29:14 +0000
commit36880493cb16e87feb83484498fcd3cc871eb68d (patch)
tree277127cf0e6c6990577935c5bb5dff9269c605b0 /packages/backend/src
parentMerge pull request #14924 from misskey-dev/develop (diff)
parentRelease: 2025.1.0 (diff)
downloadmisskey-36880493cb16e87feb83484498fcd3cc871eb68d.tar.gz
misskey-36880493cb16e87feb83484498fcd3cc871eb68d.tar.bz2
misskey-36880493cb16e87feb83484498fcd3cc871eb68d.zip
Merge pull request #15279 from misskey-dev/develop
Release: 2025.1.0
Diffstat (limited to 'packages/backend/src')
-rw-r--r--packages/backend/src/GlobalModule.ts10
-rw-r--r--packages/backend/src/boot/entry.ts20
-rw-r--r--packages/backend/src/boot/master.ts25
-rw-r--r--packages/backend/src/config.ts23
-rw-r--r--packages/backend/src/const.ts12
-rw-r--r--packages/backend/src/core/AbuseReportNotificationService.ts32
-rw-r--r--packages/backend/src/core/AiService.ts25
-rw-r--r--packages/backend/src/core/CaptchaService.ts299
-rw-r--r--packages/backend/src/core/CustomEmojiService.ts224
-rw-r--r--packages/backend/src/core/FetchInstanceMetadataService.ts12
-rw-r--r--packages/backend/src/core/FileInfoService.ts4
-rw-r--r--packages/backend/src/core/MfmService.ts33
-rw-r--r--packages/backend/src/core/NoteCreateService.ts35
-rw-r--r--packages/backend/src/core/S3Service.ts2
-rw-r--r--packages/backend/src/core/SearchService.ts274
-rw-r--r--packages/backend/src/core/SystemWebhookService.ts31
-rw-r--r--packages/backend/src/core/UserBlockingService.ts8
-rw-r--r--packages/backend/src/core/UserFollowingService.ts32
-rw-r--r--packages/backend/src/core/UserService.ts9
-rw-r--r--packages/backend/src/core/UserWebhookService.ts25
-rw-r--r--packages/backend/src/core/UtilityService.ts7
-rw-r--r--packages/backend/src/core/WebAuthnService.ts4
-rw-r--r--packages/backend/src/core/activitypub/ApRendererService.ts3
-rw-r--r--packages/backend/src/core/activitypub/ApResolverService.ts25
-rw-r--r--packages/backend/src/core/activitypub/misc/check-against-url.ts6
-rw-r--r--packages/backend/src/core/activitypub/misc/contexts.ts5
-rw-r--r--packages/backend/src/core/activitypub/models/ApNoteService.ts14
-rw-r--r--packages/backend/src/core/activitypub/models/ApPersonService.ts20
-rw-r--r--packages/backend/src/core/activitypub/type.ts5
-rw-r--r--packages/backend/src/core/chart/ChartManagementService.ts10
-rw-r--r--packages/backend/src/core/entities/EmojiEntityService.ts90
-rw-r--r--packages/backend/src/core/entities/MetaEntityService.ts1
-rw-r--r--packages/backend/src/core/entities/NoteEntityService.ts9
-rw-r--r--packages/backend/src/misc/json-schema.ts7
-rw-r--r--packages/backend/src/models/json-schema/emoji.ts83
-rw-r--r--packages/backend/src/models/json-schema/meta.ts5
-rw-r--r--packages/backend/src/postgres.ts59
-rw-r--r--packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts26
-rw-r--r--packages/backend/src/queue/processors/CleanChartsProcessorService.ts27
-rw-r--r--packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts5
-rw-r--r--packages/backend/src/queue/processors/ResyncChartsProcessorService.ts9
-rw-r--r--packages/backend/src/queue/processors/TickChartsProcessorService.ts27
-rw-r--r--packages/backend/src/queue/types.ts17
-rw-r--r--packages/backend/src/server/ActivityPubServerService.ts4
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts1538
-rw-r--r--packages/backend/src/server/api/endpoint-list.ts399
-rw-r--r--packages/backend/src/server/api/endpoints.ts780
-rw-r--r--packages/backend/src/server/api/endpoints/admin/captcha/current.ts70
-rw-r--r--packages/backend/src/server/api/endpoints/admin/captcha/save.ts129
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/add.ts31
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/copy.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/update.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/ap/show.ts65
-rw-r--r--packages/backend/src/server/api/endpoints/i/apps.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/i/update.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/pages/update.ts20
-rw-r--r--packages/backend/src/server/api/endpoints/v2/admin/emoji/list.ts126
-rw-r--r--packages/backend/src/server/api/openapi/gen-spec.ts2
-rw-r--r--packages/backend/src/server/api/openapi/schemas.ts4
-rw-r--r--packages/backend/src/server/api/stream/channels/hybrid-timeline.ts1
-rw-r--r--packages/backend/src/server/web/ClientServerService.ts15
61 files changed, 2055 insertions, 2742 deletions
diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts
index 6ae8ccfbb3..ace7f7841c 100644
--- a/packages/backend/src/GlobalModule.ts
+++ b/packages/backend/src/GlobalModule.ts
@@ -7,14 +7,14 @@ import { Global, Inject, Module } from '@nestjs/common';
import * as Redis from 'ioredis';
import { DataSource } from 'typeorm';
import { MeiliSearch } from 'meilisearch';
+import { MiMeta } from '@/models/Meta.js';
import { DI } from './di-symbols.js';
import { Config, loadConfig } from './config.js';
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';
+import type { Provider, OnApplicationShutdown } from '@nestjs/common';
const $config: Provider = {
provide: DI.config,
@@ -33,7 +33,11 @@ const $db: Provider = {
const $meilisearch: Provider = {
provide: DI.meilisearch,
useFactory: (config: Config) => {
- if (config.meilisearch) {
+ if (config.fulltextSearch?.provider === 'meilisearch') {
+ if (!config.meilisearch) {
+ throw new Error('MeiliSearch is enabled but no configuration is provided');
+ }
+
return new MeiliSearch({
host: `${config.meilisearch.ssl ? 'https' : 'http'}://${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.apiKey,
diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts
index 25375c3015..da585ad68d 100644
--- a/packages/backend/src/boot/entry.ts
+++ b/packages/backend/src/boot/entry.ts
@@ -68,16 +68,22 @@ process.on('exit', code => {
//#endregion
-if (cluster.isPrimary || envOption.disableClustering) {
- await masterMain();
-
+if (!envOption.disableClustering) {
if (cluster.isPrimary) {
+ logger.info(`Start main process... pid: ${process.pid}`);
+ await masterMain();
ev.mount();
+ } else if (cluster.isWorker) {
+ logger.info(`Start worker process... pid: ${process.pid}`);
+ await workerMain();
+ } else {
+ throw new Error('Unknown process type');
}
-}
-
-if (cluster.isWorker || envOption.disableClustering) {
- await workerMain();
+} else {
+ // 非clusterの場合はMasterのみが起動するため、Workerの処理は行わない(cluster.isWorker === trueの状態でこのブロックに来ることはない)
+ logger.info(`Start main process... pid: ${process.pid}`);
+ await masterMain();
+ ev.mount();
}
readyRef.value = true;
diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts
index 4bc5c799cf..d1fb3858db 100644
--- a/packages/backend/src/boot/master.ts
+++ b/packages/backend/src/boot/master.ts
@@ -91,25 +91,36 @@ export async function masterMain() {
});
}
- if (envOption.disableClustering) {
+ bootLogger.info(
+ `mode: [disableClustering: ${envOption.disableClustering}, onlyServer: ${envOption.onlyServer}, onlyQueue: ${envOption.onlyQueue}]`,
+ );
+
+ if (!envOption.disableClustering) {
+ // clusterモジュール有効時
+
if (envOption.onlyServer) {
- await server();
+ // onlyServer かつ enableCluster な場合、メインプロセスはforkのみに制限する(listenしない)。
+ // ワーカープロセス側でlistenすると、メインプロセスでポートへの着信を受け入れてワーカープロセスへの分配を行う動作をする。
+ // そのため、メインプロセスでも直接listenするとポートの競合が発生して起動に失敗してしまう。
+ // see: https://nodejs.org/api/cluster.html#cluster
} else if (envOption.onlyQueue) {
await jobQueue();
} else {
await server();
- await jobQueue();
}
+
+ await spawnWorkers(config.clusterLimit);
} else {
+ // clusterモジュール無効時
+
if (envOption.onlyServer) {
- // nop
+ await server();
} else if (envOption.onlyQueue) {
- // nop
+ await jobQueue();
} else {
await server();
+ await jobQueue();
}
-
- await spawnWorkers(config.clusterLimit);
}
if (envOption.onlyQueue) {
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts
index 42f1033b9d..c0b1484804 100644
--- a/packages/backend/src/config.ts
+++ b/packages/backend/src/config.ts
@@ -50,6 +50,9 @@ type Source = {
redisForJobQueue?: RedisOptionsSource;
redisForTimelines?: RedisOptionsSource;
redisForReactions?: RedisOptionsSource;
+ fulltextSearch?: {
+ provider?: FulltextSearchProvider;
+ };
meilisearch?: {
host: string;
port: string;
@@ -99,6 +102,13 @@ type Source = {
perUserNotificationsMaxCount?: number;
deactivateAntennaThreshold?: number;
pidFile: string;
+
+ logging?: {
+ sql?: {
+ disableQueryTruncation? : boolean,
+ enableQueryParamLogging? : boolean,
+ }
+ }
};
export type Config = {
@@ -124,6 +134,9 @@ export type Config = {
user: string;
pass: string;
}[] | undefined;
+ fulltextSearch?: {
+ provider?: FulltextSearchProvider;
+ };
meilisearch: {
host: string;
port: string;
@@ -151,6 +164,12 @@ export type Config = {
inboxJobMaxAttempts: number | undefined;
proxyRemoteFiles: boolean | undefined;
signToActivityPubGet: boolean | undefined;
+ logging?: {
+ sql?: {
+ disableQueryTruncation? : boolean,
+ enableQueryParamLogging? : boolean,
+ }
+ }
version: string;
publishTarballInsteadOfProvideRepositoryUrl: boolean;
@@ -184,6 +203,8 @@ export type Config = {
pidFile: string;
};
+export type FulltextSearchProvider = 'sqlLike' | 'sqlPgroonga' | 'meilisearch';
+
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@@ -252,6 +273,7 @@ export function loadConfig(): Config {
db: { ...config.db, db: dbDb, user: dbUser, pass: dbPass },
dbReplications: config.dbReplications,
dbSlaves: config.dbSlaves,
+ fulltextSearch: config.fulltextSearch,
meilisearch: config.meilisearch,
redis,
redisForPubsub: config.redisForPubsub ? convertRedisOptions(config.redisForPubsub, host) : redis,
@@ -293,6 +315,7 @@ export function loadConfig(): Config {
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7),
pidFile: config.pidFile,
+ logging: config.logging,
};
}
diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts
index e3a61861f4..1ca0397206 100644
--- a/packages/backend/src/const.ts
+++ b/packages/backend/src/const.ts
@@ -26,6 +26,18 @@ export const DB_MAX_NOTE_TEXT_LENGTH = 8192;
export const DB_MAX_IMAGE_COMMENT_LENGTH = 512;
//#endregion
+export const FILE_TYPE_IMAGE = [
+ 'image/png',
+ 'image/gif',
+ 'image/jpeg',
+ 'image/webp',
+ 'image/avif',
+ 'image/apng',
+ 'image/bmp',
+ 'image/tiff',
+ 'image/x-icon',
+];
+
// ブラウザで直接表示することを許可するファイルの種類のリスト
// ここに含まれないものは application/octet-stream としてレスポンスされる
// SVGはXSSを生むので許可しない
diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts
index 742e2621fd..9bca795479 100644
--- a/packages/backend/src/core/AbuseReportNotificationService.ts
+++ b/packages/backend/src/core/AbuseReportNotificationService.ts
@@ -160,22 +160,22 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
};
});
- const recipientWebhookIds = await this.fetchWebhookRecipients()
- .then(it => it
- .filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook')
- .map(it => it.systemWebhookId)
- .filter(x => x != null));
- for (const webhookId of recipientWebhookIds) {
- await Promise.all(
- convertedReports.map(it => {
- return this.systemWebhookService.enqueueSystemWebhook(
- webhookId,
- type,
- it,
- );
- }),
- );
- }
+ const inactiveRecipients = await this.fetchWebhookRecipients()
+ .then(it => it.filter(it => !it.isActive));
+ const withoutWebhookIds = inactiveRecipients
+ .map(it => it.systemWebhookId)
+ .filter(x => x != null);
+ return Promise.all(
+ convertedReports.map(it => {
+ return this.systemWebhookService.enqueueSystemWebhook(
+ type,
+ it,
+ {
+ excludes: withoutWebhookIds,
+ },
+ );
+ }),
+ );
}
/**
diff --git a/packages/backend/src/core/AiService.ts b/packages/backend/src/core/AiService.ts
index ad852fdd6e..248a9b8979 100644
--- a/packages/backend/src/core/AiService.ts
+++ b/packages/backend/src/core/AiService.ts
@@ -10,12 +10,13 @@ import { Injectable } from '@nestjs/common';
import * as nsfw from 'nsfwjs';
import si from 'systeminformation';
import { Mutex } from 'async-mutex';
+import fetch from 'node-fetch';
import { bindThis } from '@/decorators.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
-const REQUIRED_CPU_FLAGS = ['avx2', 'fma'];
+const REQUIRED_CPU_FLAGS_X64 = ['avx2', 'fma'];
let isSupportedCpu: undefined | boolean = undefined;
@Injectable()
@@ -28,11 +29,10 @@ export class AiService {
}
@bindThis
- public async detectSensitive(path: string): Promise<nsfw.predictionType[] | null> {
+ public async detectSensitive(path: string): Promise<nsfw.PredictionType[] | null> {
try {
if (isSupportedCpu === undefined) {
- const cpuFlags = await this.getCpuFlags();
- isSupportedCpu = REQUIRED_CPU_FLAGS.every(required => cpuFlags.includes(required));
+ isSupportedCpu = await this.computeIsSupportedCpu();
}
if (!isSupportedCpu) {
@@ -41,6 +41,7 @@ export class AiService {
}
const tf = await import('@tensorflow/tfjs-node');
+ tf.env().global.fetch = fetch;
if (this.model == null) {
await this.modelLoadMutex.runExclusive(async () => {
@@ -64,6 +65,22 @@ export class AiService {
}
}
+ private async computeIsSupportedCpu(): Promise<boolean> {
+ switch (process.arch) {
+ case 'x64': {
+ const cpuFlags = await this.getCpuFlags();
+ return REQUIRED_CPU_FLAGS_X64.every(required => cpuFlags.includes(required));
+ }
+ case 'arm64': {
+ // As far as I know, no required CPU flags for ARM64.
+ return true;
+ }
+ default: {
+ return false;
+ }
+ }
+ }
+
@bindThis
private async getCpuFlags(): Promise<string[]> {
const str = await si.cpuFlags();
diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts
index 206d0dbe0a..8c7f66236e 100644
--- a/packages/backend/src/core/CaptchaService.ts
+++ b/packages/backend/src/core/CaptchaService.ts
@@ -6,6 +6,65 @@
import { Injectable } from '@nestjs/common';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { bindThis } from '@/decorators.js';
+import { MetaService } from '@/core/MetaService.js';
+import { MiMeta } from '@/models/Meta.js';
+import Logger from '@/logger.js';
+import { LoggerService } from './LoggerService.js';
+
+export const supportedCaptchaProviders = ['none', 'hcaptcha', 'mcaptcha', 'recaptcha', 'turnstile', 'testcaptcha'] as const;
+export type CaptchaProvider = typeof supportedCaptchaProviders[number];
+
+export const captchaErrorCodes = {
+ invalidProvider: Symbol('invalidProvider'),
+ invalidParameters: Symbol('invalidParameters'),
+ noResponseProvided: Symbol('noResponseProvided'),
+ requestFailed: Symbol('requestFailed'),
+ verificationFailed: Symbol('verificationFailed'),
+ unknown: Symbol('unknown'),
+} as const;
+export type CaptchaErrorCode = typeof captchaErrorCodes[keyof typeof captchaErrorCodes];
+
+export type CaptchaSetting = {
+ provider: CaptchaProvider;
+ hcaptcha: {
+ siteKey: string | null;
+ secretKey: string | null;
+ }
+ mcaptcha: {
+ siteKey: string | null;
+ secretKey: string | null;
+ instanceUrl: string | null;
+ }
+ recaptcha: {
+ siteKey: string | null;
+ secretKey: string | null;
+ }
+ turnstile: {
+ siteKey: string | null;
+ secretKey: string | null;
+ }
+}
+
+export class CaptchaError extends Error {
+ public readonly code: CaptchaErrorCode;
+ public readonly cause?: unknown;
+
+ constructor(code: CaptchaErrorCode, message: string, cause?: unknown) {
+ super(message);
+ this.code = code;
+ this.cause = cause;
+ this.name = 'CaptchaError';
+ }
+}
+
+export type CaptchaSaveSuccess = {
+ success: true;
+}
+export type CaptchaSaveFailure = {
+ success: false;
+ error: CaptchaError;
+}
+export type CaptchaSaveResult = CaptchaSaveSuccess | CaptchaSaveFailure;
type CaptchaResponse = {
success: boolean;
@@ -14,9 +73,14 @@ type CaptchaResponse = {
@Injectable()
export class CaptchaService {
+ private readonly logger: Logger;
+
constructor(
private httpRequestService: HttpRequestService,
+ private metaService: MetaService,
+ loggerService: LoggerService,
) {
+ this.logger = loggerService.getLogger('captcha');
}
@bindThis
@@ -44,32 +108,32 @@ export class CaptchaService {
@bindThis
public async verifyRecaptcha(secret: string, response: string | null | undefined): Promise<void> {
if (response == null) {
- throw new Error('recaptcha-failed: no response provided');
+ throw new CaptchaError(captchaErrorCodes.noResponseProvided, 'recaptcha-failed: no response provided');
}
const result = await this.getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(err => {
- throw new Error(`recaptcha-request-failed: ${err}`);
+ throw new CaptchaError(captchaErrorCodes.requestFailed, `recaptcha-request-failed: ${err}`);
});
if (result.success !== true) {
const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : '';
- throw new Error(`recaptcha-failed: ${errorCodes}`);
+ throw new CaptchaError(captchaErrorCodes.verificationFailed, `recaptcha-failed: ${errorCodes}`);
}
}
@bindThis
public async verifyHcaptcha(secret: string, response: string | null | undefined): Promise<void> {
if (response == null) {
- throw new Error('hcaptcha-failed: no response provided');
+ throw new CaptchaError(captchaErrorCodes.noResponseProvided, 'hcaptcha-failed: no response provided');
}
const result = await this.getCaptchaResponse('https://hcaptcha.com/siteverify', secret, response).catch(err => {
- throw new Error(`hcaptcha-request-failed: ${err}`);
+ throw new CaptchaError(captchaErrorCodes.requestFailed, `hcaptcha-request-failed: ${err}`);
});
if (result.success !== true) {
const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : '';
- throw new Error(`hcaptcha-failed: ${errorCodes}`);
+ throw new CaptchaError(captchaErrorCodes.verificationFailed, `hcaptcha-failed: ${errorCodes}`);
}
}
@@ -77,7 +141,7 @@ export class CaptchaService {
@bindThis
public async verifyMcaptcha(secret: string, siteKey: string, instanceHost: string, response: string | null | undefined): Promise<void> {
if (response == null) {
- throw new Error('mcaptcha-failed: no response provided');
+ throw new CaptchaError(captchaErrorCodes.noResponseProvided, 'mcaptcha-failed: no response provided');
}
const endpointUrl = new URL('/api/v1/pow/siteverify', instanceHost);
@@ -91,46 +155,251 @@ export class CaptchaService {
headers: {
'Content-Type': 'application/json',
},
- });
+ }, { throwErrorWhenResponseNotOk: false });
if (result.status !== 200) {
- throw new Error('mcaptcha-failed: mcaptcha didn\'t return 200 OK');
+ throw new CaptchaError(captchaErrorCodes.requestFailed, 'mcaptcha-failed: mcaptcha didn\'t return 200 OK');
}
const resp = (await result.json()) as { valid: boolean };
if (!resp.valid) {
- throw new Error('mcaptcha-request-failed');
+ throw new CaptchaError(captchaErrorCodes.verificationFailed, 'mcaptcha-request-failed');
}
}
@bindThis
public async verifyTurnstile(secret: string, response: string | null | undefined): Promise<void> {
if (response == null) {
- throw new Error('turnstile-failed: no response provided');
+ throw new CaptchaError(captchaErrorCodes.noResponseProvided, 'turnstile-failed: no response provided');
}
const result = await this.getCaptchaResponse('https://challenges.cloudflare.com/turnstile/v0/siteverify', secret, response).catch(err => {
- throw new Error(`turnstile-request-failed: ${err}`);
+ throw new CaptchaError(captchaErrorCodes.requestFailed, `turnstile-request-failed: ${err}`);
});
if (result.success !== true) {
const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : '';
- throw new Error(`turnstile-failed: ${errorCodes}`);
+ throw new CaptchaError(captchaErrorCodes.verificationFailed, `turnstile-failed: ${errorCodes}`);
}
}
@bindThis
public async verifyTestcaptcha(response: string | null | undefined): Promise<void> {
if (response == null) {
- throw new Error('testcaptcha-failed: no response provided');
+ throw new CaptchaError(captchaErrorCodes.noResponseProvided, 'testcaptcha-failed: no response provided');
}
const success = response === 'testcaptcha-passed';
if (!success) {
- throw new Error('testcaptcha-failed');
+ throw new CaptchaError(captchaErrorCodes.verificationFailed, 'testcaptcha-failed');
+ }
+ }
+
+ @bindThis
+ public async get(): Promise<CaptchaSetting> {
+ const meta = await this.metaService.fetch(true);
+
+ let provider: CaptchaProvider;
+ switch (true) {
+ case meta.enableHcaptcha: {
+ provider = 'hcaptcha';
+ break;
+ }
+ case meta.enableMcaptcha: {
+ provider = 'mcaptcha';
+ break;
+ }
+ case meta.enableRecaptcha: {
+ provider = 'recaptcha';
+ break;
+ }
+ case meta.enableTurnstile: {
+ provider = 'turnstile';
+ break;
+ }
+ case meta.enableTestcaptcha: {
+ provider = 'testcaptcha';
+ break;
+ }
+ default: {
+ provider = 'none';
+ break;
+ }
+ }
+
+ return {
+ provider: provider,
+ hcaptcha: {
+ siteKey: meta.hcaptchaSiteKey,
+ secretKey: meta.hcaptchaSecretKey,
+ },
+ mcaptcha: {
+ siteKey: meta.mcaptchaSitekey,
+ secretKey: meta.mcaptchaSecretKey,
+ instanceUrl: meta.mcaptchaInstanceUrl,
+ },
+ recaptcha: {
+ siteKey: meta.recaptchaSiteKey,
+ secretKey: meta.recaptchaSecretKey,
+ },
+ turnstile: {
+ siteKey: meta.turnstileSiteKey,
+ secretKey: meta.turnstileSecretKey,
+ },
+ };
+ }
+
+ /**
+ * captchaの設定を更新します. その際、フロントエンド側で受け取ったcaptchaからの戻り値を検証し、passした場合のみ設定を更新します.
+ * 実際の検証処理はサービス内で定義されている各captchaプロバイダの検証関数に委譲します.
+ *
+ * @param provider 検証するcaptchaのプロバイダ
+ * @param params
+ * @param params.sitekey hcaptcha, recaptcha, turnstile, mcaptchaの場合に指定するsitekey. それ以外のプロバイダでは無視されます
+ * @param params.secret hcaptcha, recaptcha, turnstile, mcaptchaの場合に指定するsecret. それ以外のプロバイダでは無視されます
+ * @param params.instanceUrl mcaptchaの場合に指定するインスタンスのURL. それ以外のプロバイダでは無視されます
+ * @param params.captchaResult フロントエンド側で受け取ったcaptchaプロバイダからの戻り値. この値を使ってサーバサイドでの検証を行います
+ * @see verifyHcaptcha
+ * @see verifyMcaptcha
+ * @see verifyRecaptcha
+ * @see verifyTurnstile
+ * @see verifyTestcaptcha
+ */
+ @bindThis
+ public async save(
+ provider: CaptchaProvider,
+ params?: {
+ sitekey?: string | null;
+ secret?: string | null;
+ instanceUrl?: string | null;
+ captchaResult?: string | null;
+ },
+ ): Promise<CaptchaSaveResult> {
+ if (!supportedCaptchaProviders.includes(provider)) {
+ return {
+ success: false,
+ error: new CaptchaError(captchaErrorCodes.invalidProvider, `Invalid captcha provider: ${provider}`),
+ };
+ }
+
+ const operation = {
+ none: async () => {
+ await this.updateMeta(provider, params);
+ },
+ hcaptcha: async () => {
+ if (!params?.secret || !params.captchaResult) {
+ throw new CaptchaError(captchaErrorCodes.invalidParameters, 'hcaptcha-failed: secret and captureResult are required');
+ }
+
+ await this.verifyHcaptcha(params.secret, params.captchaResult);
+ await this.updateMeta(provider, params);
+ },
+ mcaptcha: async () => {
+ if (!params?.secret || !params.sitekey || !params.instanceUrl || !params.captchaResult) {
+ throw new CaptchaError(captchaErrorCodes.invalidParameters, 'mcaptcha-failed: secret, sitekey, instanceUrl and captureResult are required');
+ }
+
+ await this.verifyMcaptcha(params.secret, params.sitekey, params.instanceUrl, params.captchaResult);
+ await this.updateMeta(provider, params);
+ },
+ recaptcha: async () => {
+ if (!params?.secret || !params.captchaResult) {
+ throw new CaptchaError(captchaErrorCodes.invalidParameters, 'recaptcha-failed: secret and captureResult are required');
+ }
+
+ await this.verifyRecaptcha(params.secret, params.captchaResult);
+ await this.updateMeta(provider, params);
+ },
+ turnstile: async () => {
+ if (!params?.secret || !params.captchaResult) {
+ throw new CaptchaError(captchaErrorCodes.invalidParameters, 'turnstile-failed: secret and captureResult are required');
+ }
+
+ await this.verifyTurnstile(params.secret, params.captchaResult);
+ await this.updateMeta(provider, params);
+ },
+ testcaptcha: async () => {
+ if (!params?.captchaResult) {
+ throw new CaptchaError(captchaErrorCodes.invalidParameters, 'turnstile-failed: captureResult are required');
+ }
+
+ await this.verifyTestcaptcha(params.captchaResult);
+ await this.updateMeta(provider, params);
+ },
+ }[provider];
+
+ return operation()
+ .then(() => ({ success: true }) as CaptchaSaveSuccess)
+ .catch(err => {
+ this.logger.info(err);
+ const error = err instanceof CaptchaError
+ ? err
+ : new CaptchaError(captchaErrorCodes.unknown, `unknown error: ${err}`);
+ return {
+ success: false,
+ error,
+ };
+ });
+ }
+
+ @bindThis
+ private async updateMeta(
+ provider: CaptchaProvider,
+ params?: {
+ sitekey?: string | null;
+ secret?: string | null;
+ instanceUrl?: string | null;
+ },
+ ) {
+ const metaPartial: Partial<
+ Pick<
+ MiMeta,
+ ('enableHcaptcha' | 'hcaptchaSiteKey' | 'hcaptchaSecretKey') |
+ ('enableMcaptcha' | 'mcaptchaSitekey' | 'mcaptchaSecretKey' | 'mcaptchaInstanceUrl') |
+ ('enableRecaptcha' | 'recaptchaSiteKey' | 'recaptchaSecretKey') |
+ ('enableTurnstile' | 'turnstileSiteKey' | 'turnstileSecretKey') |
+ ('enableTestcaptcha')
+ >
+ > = {
+ enableHcaptcha: provider === 'hcaptcha',
+ enableMcaptcha: provider === 'mcaptcha',
+ enableRecaptcha: provider === 'recaptcha',
+ enableTurnstile: provider === 'turnstile',
+ enableTestcaptcha: provider === 'testcaptcha',
+ };
+
+ const updateIfNotUndefined = <K extends keyof typeof metaPartial>(key: K, value: typeof metaPartial[K]) => {
+ if (value !== undefined) {
+ metaPartial[key] = value;
+ }
+ };
+ switch (provider) {
+ case 'hcaptcha': {
+ updateIfNotUndefined('hcaptchaSiteKey', params?.sitekey);
+ updateIfNotUndefined('hcaptchaSecretKey', params?.secret);
+ break;
+ }
+ case 'mcaptcha': {
+ updateIfNotUndefined('mcaptchaSitekey', params?.sitekey);
+ updateIfNotUndefined('mcaptchaSecretKey', params?.secret);
+ updateIfNotUndefined('mcaptchaInstanceUrl', params?.instanceUrl);
+ break;
+ }
+ case 'recaptcha': {
+ updateIfNotUndefined('recaptchaSiteKey', params?.sitekey);
+ updateIfNotUndefined('recaptchaSecretKey', params?.secret);
+ break;
+ }
+ case 'turnstile': {
+ updateIfNotUndefined('turnstileSiteKey', params?.sitekey);
+ updateIfNotUndefined('turnstileSecretKey', params?.secret);
+ break;
+ }
}
+
+ await this.metaService.update(metaPartial);
}
}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 4566113449..da71a5de6f 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -4,24 +4,59 @@
*/
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
-import { In, IsNull } from 'typeorm';
import * as Redis from 'ioredis';
-import { DI } from '@/di-symbols.js';
-import { IdService } from '@/core/IdService.js';
+import { In, IsNull } from 'typeorm';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
-import type { MiDriveFile } from '@/models/DriveFile.js';
-import type { MiEmoji } from '@/models/Emoji.js';
-import type { EmojisRepository, MiRole, MiUser } from '@/models/_.js';
+import { IdService } from '@/core/IdService.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
+import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
+import { DI } from '@/di-symbols.js';
import { MemoryKVCache, RedisSingleCache } from '@/misc/cache.js';
-import { UtilityService } from '@/core/UtilityService.js';
-import { query } from '@/misc/prelude/url.js';
+import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
+import type { EmojisRepository, MiRole, MiUser } from '@/models/_.js';
+import type { MiEmoji } from '@/models/Emoji.js';
import type { Serialized } from '@/types.js';
-import { ModerationLogService } from '@/core/ModerationLogService.js';
const parseEmojiStrRegexp = /^([-\w]+)(?:@([\w.-]+))?$/;
+export const fetchEmojisHostTypes = [
+ 'local',
+ 'remote',
+ 'all',
+] as const;
+export type FetchEmojisHostTypes = typeof fetchEmojisHostTypes[number];
+export const fetchEmojisSortKeys = [
+ '+id',
+ '-id',
+ '+updatedAt',
+ '-updatedAt',
+ '+name',
+ '-name',
+ '+host',
+ '-host',
+ '+uri',
+ '-uri',
+ '+publicUrl',
+ '-publicUrl',
+ '+type',
+ '-type',
+ '+aliases',
+ '-aliases',
+ '+category',
+ '-category',
+ '+license',
+ '-license',
+ '+isSensitive',
+ '-isSensitive',
+ '+localOnly',
+ '-localOnly',
+ '+roleIdsThatCanBeUsedThisEmojiAsReaction',
+ '-roleIdsThatCanBeUsedThisEmojiAsReaction',
+] as const;
+export type FetchEmojisSortKeys = typeof fetchEmojisSortKeys[number];
+
@Injectable()
export class CustomEmojiService implements OnApplicationShutdown {
private emojisCache: MemoryKVCache<MiEmoji | null>;
@@ -30,10 +65,8 @@ export class CustomEmojiService implements OnApplicationShutdown {
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
-
@Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository,
-
private utilityService: UtilityService,
private idService: IdService,
private emojiEntityService: EmojiEntityService,
@@ -58,7 +91,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis
public async add(data: {
- driveFile: MiDriveFile;
+ originalUrl: string;
+ publicUrl: string;
+ fileType: string;
name: string;
category: string | null;
aliases: string[];
@@ -75,9 +110,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
category: data.category,
host: data.host,
aliases: data.aliases,
- originalUrl: data.driveFile.url,
- publicUrl: data.driveFile.webpublicUrl ?? data.driveFile.url,
- type: data.driveFile.webpublicType ?? data.driveFile.type,
+ originalUrl: data.originalUrl,
+ publicUrl: data.publicUrl,
+ type: data.fileType,
license: data.license,
isSensitive: data.isSensitive,
localOnly: data.localOnly,
@@ -105,8 +140,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis
public async update(data: (
{ id: MiEmoji['id'], name?: string; } | { name: string; id?: MiEmoji['id'], }
- ) & {
- driveFile?: MiDriveFile;
+ ) & {
+ originalUrl?: string;
+ publicUrl?: string;
+ fileType?: string;
category?: string | null;
aliases?: string[];
license?: string | null;
@@ -139,9 +176,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
license: data.license,
isSensitive: data.isSensitive,
localOnly: data.localOnly,
- originalUrl: data.driveFile != null ? data.driveFile.url : undefined,
- publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined,
- type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined,
+ originalUrl: data.originalUrl,
+ publicUrl: data.publicUrl,
+ type: data.fileType,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined,
});
@@ -308,7 +345,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis
private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null {
- // クエリに使うホスト
+ // クエリに使うホスト
let host = src === '.' ? null // .はローカルホスト (ここがマッチするのはリアクションのみ)
: src === undefined ? noteUserHost // ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない)
: this.utilityService.isSelfHost(src) ? null // 自ホスト指定
@@ -415,6 +452,151 @@ export class CustomEmojiService implements OnApplicationShutdown {
}
@bindThis
+ public async fetchEmojis(
+ params?: {
+ query?: {
+ updatedAtFrom?: string;
+ updatedAtTo?: string;
+ name?: string;
+ host?: string;
+ uri?: string;
+ publicUrl?: string;
+ type?: string;
+ aliases?: string;
+ category?: string;
+ license?: string;
+ isSensitive?: boolean;
+ localOnly?: boolean;
+ hostType?: FetchEmojisHostTypes;
+ roleIds?: string[];
+ },
+ sinceId?: string;
+ untilId?: string;
+ },
+ opts?: {
+ limit?: number;
+ page?: number;
+ sortKeys?: FetchEmojisSortKeys[]
+ },
+ ) {
+ function multipleWordsToQuery(words: string) {
+ return words.split(/\s/).filter(x => x.length > 0).map(x => `%${sqlLikeEscape(x)}%`);
+ }
+
+ const builder = this.emojisRepository.createQueryBuilder('emoji');
+ if (params?.query) {
+ const q = params.query;
+ if (q.updatedAtFrom) {
+ // noIndexScan
+ builder.andWhere('CAST(emoji.updatedAt AS DATE) >= :updateAtFrom', { updateAtFrom: q.updatedAtFrom });
+ }
+ if (q.updatedAtTo) {
+ // noIndexScan
+ builder.andWhere('CAST(emoji.updatedAt AS DATE) <= :updateAtTo', { updateAtTo: q.updatedAtTo });
+ }
+ if (q.name) {
+ builder.andWhere('emoji.name ~~ ANY(ARRAY[:...name])', { name: multipleWordsToQuery(q.name) });
+ }
+
+ switch (true) {
+ case q.hostType === 'local': {
+ builder.andWhere('emoji.host IS NULL');
+ break;
+ }
+ case q.hostType === 'remote': {
+ if (q.host) {
+ // noIndexScan
+ builder.andWhere('emoji.host ~~ ANY(ARRAY[:...host])', { host: multipleWordsToQuery(q.host) });
+ } else {
+ builder.andWhere('emoji.host IS NOT NULL');
+ }
+ break;
+ }
+ }
+
+ if (q.uri) {
+ // noIndexScan
+ builder.andWhere('emoji.uri ~~ ANY(ARRAY[:...uri])', { uri: multipleWordsToQuery(q.uri) });
+ }
+ if (q.publicUrl) {
+ // noIndexScan
+ builder.andWhere('emoji.publicUrl ~~ ANY(ARRAY[:...publicUrl])', { publicUrl: multipleWordsToQuery(q.publicUrl) });
+ }
+ if (q.type) {
+ // noIndexScan
+ builder.andWhere('emoji.type ~~ ANY(ARRAY[:...type])', { type: multipleWordsToQuery(q.type) });
+ }
+ if (q.aliases) {
+ // noIndexScan
+ const subQueryBuilder = builder.subQuery()
+ .select('COUNT(0)', 'count')
+ .from(
+ sq2 => sq2
+ .select('unnest(subEmoji.aliases)', 'alias')
+ .addSelect('subEmoji.id', 'id')
+ .from('emoji', 'subEmoji'),
+ 'aliasTable',
+ )
+ .where('"emoji"."id" = "aliasTable"."id"')
+ .andWhere('"aliasTable"."alias" ~~ ANY(ARRAY[:...aliases])', { aliases: multipleWordsToQuery(q.aliases) });
+
+ builder.andWhere(`(${subQueryBuilder.getQuery()}) > 0`);
+ }
+ if (q.category) {
+ builder.andWhere('emoji.category ~~ ANY(ARRAY[:...category])', { category: multipleWordsToQuery(q.category) });
+ }
+ if (q.license) {
+ // noIndexScan
+ builder.andWhere('emoji.license ~~ ANY(ARRAY[:...license])', { license: multipleWordsToQuery(q.license) });
+ }
+ if (q.isSensitive != null) {
+ // noIndexScan
+ builder.andWhere('emoji.isSensitive = :isSensitive', { isSensitive: q.isSensitive });
+ }
+ if (q.localOnly != null) {
+ // noIndexScan
+ builder.andWhere('emoji.localOnly = :localOnly', { localOnly: q.localOnly });
+ }
+ if (q.roleIds && q.roleIds.length > 0) {
+ builder.andWhere('emoji.roleIdsThatCanBeUsedThisEmojiAsReaction && ARRAY[:...roleIds]::VARCHAR[]', { roleIds: q.roleIds });
+ }
+ }
+
+ if (params?.sinceId) {
+ builder.andWhere('emoji.id > :sinceId', { sinceId: params.sinceId });
+ }
+ if (params?.untilId) {
+ builder.andWhere('emoji.id < :untilId', { untilId: params.untilId });
+ }
+
+ if (opts?.sortKeys && opts.sortKeys.length > 0) {
+ for (const sortKey of opts.sortKeys) {
+ const direction = sortKey.startsWith('-') ? 'DESC' : 'ASC';
+ const key = sortKey.replace(/^[+-]/, '');
+ builder.addOrderBy(`emoji.${key}`, direction);
+ }
+ } else {
+ builder.addOrderBy('emoji.id', 'DESC');
+ }
+
+ const limit = opts?.limit ?? 10;
+ if (opts?.page) {
+ builder.skip((opts.page - 1) * limit);
+ }
+
+ builder.take(limit);
+
+ const [emojis, count] = await builder.getManyAndCount();
+
+ return {
+ emojis,
+ count: (count > limit ? emojis.length : count),
+ allCount: count,
+ allPages: Math.ceil(count / limit),
+ };
+ }
+
+ @bindThis
public dispose(): void {
this.emojisCache.dispose();
}
diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts
index 987999bce7..ce3af7c774 100644
--- a/packages/backend/src/core/FetchInstanceMetadataService.ts
+++ b/packages/backend/src/core/FetchInstanceMetadataService.ts
@@ -181,7 +181,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async fetchDom(instance: MiInstance): Promise<DOMWindow['document']> {
+ private async fetchDom(instance: MiInstance): Promise<Document> {
this.logger.info(`Fetching HTML of ${instance.host} ...`);
const url = 'https://' + instance.host;
@@ -206,7 +206,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async fetchFaviconUrl(instance: MiInstance, doc: DOMWindow['document'] | null): Promise<string | null> {
+ private async fetchFaviconUrl(instance: MiInstance, doc: Document | null): Promise<string | null> {
const url = 'https://' + instance.host;
if (doc) {
@@ -232,7 +232,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async fetchIconUrl(instance: MiInstance, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+ private async fetchIconUrl(instance: MiInstance, doc: Document | null, manifest: Record<string, any> | null): Promise<string | null> {
if (manifest && manifest.icons && manifest.icons.length > 0 && manifest.icons[0].src) {
const url = 'https://' + instance.host;
return (new URL(manifest.icons[0].src, url)).href;
@@ -261,7 +261,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async getThemeColor(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+ private async getThemeColor(info: NodeInfo | null, doc: Document | null, manifest: Record<string, any> | null): Promise<string | null> {
const themeColor = info?.metadata?.themeColor ?? doc?.querySelector('meta[name="theme-color"]')?.getAttribute('content') ?? manifest?.theme_color;
if (themeColor) {
@@ -273,7 +273,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+ private async getSiteName(info: NodeInfo | null, doc: Document | null, manifest: Record<string, any> | null): Promise<string | null> {
if (info && info.metadata) {
if (typeof info.metadata.nodeName === 'string') {
return info.metadata.nodeName;
@@ -298,7 +298,7 @@ export class FetchInstanceMetadataService {
}
@bindThis
- private async getDescription(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+ private async getDescription(info: NodeInfo | null, doc: Document | null, manifest: Record<string, any> | null): Promise<string | null> {
if (info && info.metadata) {
if (typeof info.metadata.nodeDescription === 'string') {
return info.metadata.nodeDescription;
diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts
index 6bd6cb8d9b..fc68eb4836 100644
--- a/packages/backend/src/core/FileInfoService.ts
+++ b/packages/backend/src/core/FileInfoService.ts
@@ -13,7 +13,6 @@ import * as fileType from 'file-type';
import FFmpeg from 'fluent-ffmpeg';
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 * as blurhash from 'blurhash';
import { createTempDir } from '@/misc/create-temp.js';
@@ -21,6 +20,7 @@ import { AiService } from '@/core/AiService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js';
+import type { PredictionType } from 'nsfwjs';
export type FileInfo = {
size: number;
@@ -170,7 +170,7 @@ export class FileInfoService {
let sensitive = false;
let porn = false;
- function judgePrediction(result: readonly predictionType[]): [sensitive: boolean, porn: boolean] {
+ function judgePrediction(result: readonly PredictionType[]): [sensitive: boolean, porn: boolean] {
let sensitive = false;
let porn = false;
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index 8061622340..bf06d4457e 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -171,6 +171,39 @@ export class MfmService {
break;
}
+ case 'ruby': {
+ let ruby: [string, string][] = [];
+ for (const child of node.childNodes) {
+ if (child.nodeName === 'rp') {
+ continue;
+ }
+ if (treeAdapter.isTextNode(child) && !/\s|\[|\]/.test(child.value)) {
+ ruby.push([child.value, '']);
+ continue;
+ }
+ if (child.nodeName === 'rt' && ruby.length > 0) {
+ const rt = getText(child);
+ if (/\s|\[|\]/.test(rt)) {
+ // If any space is included in rt, it is treated as a normal text
+ ruby = [];
+ appendChildren(node.childNodes);
+ break;
+ } else {
+ ruby.at(-1)![1] = rt;
+ continue;
+ }
+ }
+ // If any other element is included in ruby, it is treated as a normal text
+ ruby = [];
+ appendChildren(node.childNodes);
+ break;
+ }
+ for (const [base, rt] of ruby) {
+ text += `$[ruby ${base} ${rt}]`;
+ }
+ break;
+ }
+
// block code (<pre><code>)
case 'pre': {
if (node.childNodes.length === 1 && node.childNodes[0].nodeName === 'code') {
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
index 56ddcefd7c..8a79908e82 100644
--- a/packages/backend/src/core/NoteCreateService.ts
+++ b/packages/backend/src/core/NoteCreateService.ts
@@ -614,14 +614,7 @@ export class NoteCreateService implements OnApplicationShutdown {
this.roleService.addNoteToRoleTimeline(noteObj);
- this.webhookService.getActiveWebhooks().then(webhooks => {
- webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'note', {
- note: noteObj,
- });
- }
- });
+ this.webhookService.enqueueUserWebhook(user.id, 'note', { note: noteObj });
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
@@ -641,13 +634,7 @@ export class NoteCreateService implements OnApplicationShutdown {
if (!isThreadMuted) {
nm.push(data.reply.userId, 'reply');
this.globalEventService.publishMainStream(data.reply.userId, 'reply', noteObj);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.reply!.userId && x.on.includes('reply'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'reply', {
- note: noteObj,
- });
- }
+ this.webhookService.enqueueUserWebhook(data.reply.userId, 'reply', { note: noteObj });
}
}
}
@@ -664,20 +651,14 @@ export class NoteCreateService implements OnApplicationShutdown {
// Publish event
if ((user.id !== data.renote.userId) && data.renote.userHost === null) {
this.globalEventService.publishMainStream(data.renote.userId, 'renote', noteObj);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.renote!.userId && x.on.includes('renote'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'renote', {
- note: noteObj,
- });
- }
+ this.webhookService.enqueueUserWebhook(data.renote.userId, 'renote', { note: noteObj });
}
}
nm.notify();
//#region AP deliver
- if (this.userEntityService.isLocalUser(user)) {
+ if (!data.localOnly && this.userEntityService.isLocalUser(user)) {
(async () => {
const noteActivity = await this.renderNoteOrRenoteActivity(data, note);
const dm = this.apDeliverManagerService.createDeliverManager(user, noteActivity);
@@ -796,13 +777,7 @@ export class NoteCreateService implements OnApplicationShutdown {
});
this.globalEventService.publishMainStream(u.id, 'mention', detailPackedNote);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === u.id && x.on.includes('mention'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'mention', {
- note: detailPackedNote,
- });
- }
+ this.webhookService.enqueueUserWebhook(u.id, 'mention', { note: detailPackedNote });
// Create notification
nm.push(u.id, 'mention');
diff --git a/packages/backend/src/core/S3Service.ts b/packages/backend/src/core/S3Service.ts
index bb2a463354..37721d2bf1 100644
--- a/packages/backend/src/core/S3Service.ts
+++ b/packages/backend/src/core/S3Service.ts
@@ -28,7 +28,7 @@ export class S3Service {
? `${meta.objectStorageUseSSL ? 'https' : 'http'}://${meta.objectStorageEndpoint}`
: `${meta.objectStorageUseSSL ? 'https' : 'http'}://example.net`; // dummy url to select http(s) agent
- const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy);
+ const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy, true);
const handlerOption: NodeHttpHandlerOptions = {};
if (meta.objectStorageUseSSL) {
handlerOption.httpsAgent = agent as https.Agent;
diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts
index edfc470375..64e3f2f56a 100644
--- a/packages/backend/src/core/SearchService.ts
+++ b/packages/backend/src/core/SearchService.ts
@@ -6,16 +6,17 @@
import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
-import type { Config } from '@/config.js';
+import { type Config, FulltextSearchProvider } from '@/config.js';
import { bindThis } from '@/decorators.js';
import { MiNote } from '@/models/Note.js';
-import { MiUser } from '@/models/_.js';
import type { NotesRepository } from '@/models/_.js';
+import { MiUser } from '@/models/_.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { CacheService } from '@/core/CacheService.js';
import { QueryService } from '@/core/QueryService.js';
import { IdService } from '@/core/IdService.js';
+import { LoggerService } from '@/core/LoggerService.js';
import type { Index, MeiliSearch } from 'meilisearch';
type K = string;
@@ -27,12 +28,24 @@ type Q =
{ op: '<', k: K, v: number } |
{ op: '>=', k: K, v: number } |
{ op: '<=', k: K, v: number } |
- { op: 'is null', k: K} |
- { op: 'is not null', k: K} |
+ { op: 'is null', k: K } |
+ { op: 'is not null', k: K } |
{ op: 'and', qs: Q[] } |
{ op: 'or', qs: Q[] } |
{ op: 'not', q: Q };
+export type SearchOpts = {
+ userId?: MiNote['userId'] | null;
+ channelId?: MiNote['channelId'] | null;
+ host?: string | null;
+};
+
+export type SearchPagination = {
+ untilId?: MiNote['id'];
+ sinceId?: MiNote['id'];
+ limit: number;
+};
+
function compileValue(value: V): string {
if (typeof value === 'string') {
return `'${value}'`; // TODO: escape
@@ -64,7 +77,8 @@ function compileQuery(q: Q): string {
@Injectable()
export class SearchService {
private readonly meilisearchIndexScope: 'local' | 'global' | string[] = 'local';
- private meilisearchNoteIndex: Index | null = null;
+ private readonly meilisearchNoteIndex: Index | null = null;
+ private readonly provider: FulltextSearchProvider;
constructor(
@Inject(DI.config)
@@ -79,6 +93,7 @@ export class SearchService {
private cacheService: CacheService,
private queryService: QueryService,
private idService: IdService,
+ private loggerService: LoggerService,
) {
if (meilisearch) {
this.meilisearchNoteIndex = meilisearch.index(`${config.meilisearch!.index}---notes`);
@@ -109,132 +124,185 @@ export class SearchService {
if (config.meilisearch?.scope) {
this.meilisearchIndexScope = config.meilisearch.scope;
}
+
+ this.provider = config.fulltextSearch?.provider ?? 'sqlLike';
+ this.loggerService.getLogger('SearchService').info(`-- Provider: ${this.provider}`);
}
@bindThis
public async indexNote(note: MiNote): Promise<void> {
+ if (!this.meilisearch) return;
if (note.text == null && note.cw == null) return;
if (!['home', 'public'].includes(note.visibility)) return;
- if (this.meilisearch) {
- switch (this.meilisearchIndexScope) {
- case 'global':
- break;
+ switch (this.meilisearchIndexScope) {
+ case 'global':
+ break;
- case 'local':
- if (note.userHost == null) break;
- return;
+ case 'local':
+ if (note.userHost == null) break;
+ return;
- default: {
- if (note.userHost == null) break;
- if (this.meilisearchIndexScope.includes(note.userHost)) break;
- return;
- }
+ default: {
+ if (note.userHost == null) break;
+ if (this.meilisearchIndexScope.includes(note.userHost)) break;
+ return;
}
-
- await this.meilisearchNoteIndex?.addDocuments([{
- id: note.id,
- createdAt: this.idService.parse(note.id).date.getTime(),
- userId: note.userId,
- userHost: note.userHost,
- channelId: note.channelId,
- cw: note.cw,
- text: note.text,
- tags: note.tags,
- }], {
- primaryKey: 'id',
- });
}
+
+ await this.meilisearchNoteIndex?.addDocuments([{
+ id: note.id,
+ createdAt: this.idService.parse(note.id).date.getTime(),
+ userId: note.userId,
+ userHost: note.userHost,
+ channelId: note.channelId,
+ cw: note.cw,
+ text: note.text,
+ tags: note.tags,
+ }], {
+ primaryKey: 'id',
+ });
}
@bindThis
public async unindexNote(note: MiNote): Promise<void> {
+ if (!this.meilisearch) return;
if (!['home', 'public'].includes(note.visibility)) return;
- if (this.meilisearch) {
- this.meilisearchNoteIndex!.deleteDocument(note.id);
- }
+ await this.meilisearchNoteIndex?.deleteDocument(note.id);
}
@bindThis
- public async searchNote(q: string, me: MiUser | null, opts: {
- userId?: MiNote['userId'] | null;
- channelId?: MiNote['channelId'] | null;
- host?: string | null;
- }, pagination: {
- untilId?: MiNote['id'];
- sinceId?: MiNote['id'];
- limit?: number;
- }): Promise<MiNote[]> {
- if (this.meilisearch) {
- const filter: Q = {
- op: 'and',
- qs: [],
- };
- if (pagination.untilId) filter.qs.push({ op: '<', k: 'createdAt', v: this.idService.parse(pagination.untilId).date.getTime() });
- if (pagination.sinceId) filter.qs.push({ op: '>', k: 'createdAt', v: this.idService.parse(pagination.sinceId).date.getTime() });
- if (opts.userId) filter.qs.push({ op: '=', k: 'userId', v: opts.userId });
- if (opts.channelId) filter.qs.push({ op: '=', k: 'channelId', v: opts.channelId });
- if (opts.host) {
- if (opts.host === '.') {
- filter.qs.push({ op: 'is null', k: 'userHost' });
- } else {
- filter.qs.push({ op: '=', k: 'userHost', v: opts.host });
- }
+ public async searchNote(
+ q: string,
+ me: MiUser | null,
+ opts: SearchOpts,
+ pagination: SearchPagination,
+ ): Promise<MiNote[]> {
+ switch (this.provider) {
+ case 'sqlLike':
+ case 'sqlPgroonga': {
+ // ほとんど内容に差がないのでsqlLikeとsqlPgroongaを同じ処理にしている.
+ // 今後の拡張で差が出る用であれば関数を分ける.
+ return this.searchNoteByLike(q, me, opts, pagination);
}
- const res = await this.meilisearchNoteIndex!.search(q, {
- sort: ['createdAt:desc'],
- matchingStrategy: 'all',
- attributesToRetrieve: ['id', 'createdAt'],
- filter: compileQuery(filter),
- limit: pagination.limit,
- });
- if (res.hits.length === 0) return [];
- const [
- userIdsWhoMeMuting,
- userIdsWhoBlockingMe,
- ] = me ? await Promise.all([
- this.cacheService.userMutingsCache.fetch(me.id),
- this.cacheService.userBlockedCache.fetch(me.id),
- ]) : [new Set<string>(), new Set<string>()];
- const notes = (await this.notesRepository.findBy({
- id: In(res.hits.map(x => x.id)),
- })).filter(note => {
- if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
- if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
- return true;
- });
- return notes.sort((a, b) => a.id > b.id ? -1 : 1);
+ case 'meilisearch': {
+ return this.searchNoteByMeiliSearch(q, me, opts, pagination);
+ }
+ default: {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const typeCheck: never = this.provider;
+ return [];
+ }
+ }
+ }
+
+ @bindThis
+ private async searchNoteByLike(
+ q: string,
+ me: MiUser | null,
+ opts: SearchOpts,
+ pagination: SearchPagination,
+ ): Promise<MiNote[]> {
+ const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), pagination.sinceId, pagination.untilId);
+
+ if (opts.userId) {
+ query.andWhere('note.userId = :userId', { userId: opts.userId });
+ } else if (opts.channelId) {
+ query.andWhere('note.channelId = :channelId', { channelId: opts.channelId });
+ }
+
+ query
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
+
+ if (this.config.fulltextSearch?.provider === 'sqlPgroonga') {
+ query.andWhere('note.text &@ :q', { q });
} else {
- const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), pagination.sinceId, pagination.untilId);
+ query.andWhere('LOWER(note.text) LIKE :q', { q: `%${ sqlLikeEscape(q.toLowerCase()) }%` });
+ }
- if (opts.userId) {
- query.andWhere('note.userId = :userId', { userId: opts.userId });
- } else if (opts.channelId) {
- query.andWhere('note.channelId = :channelId', { channelId: opts.channelId });
+ if (opts.host) {
+ if (opts.host === '.') {
+ query.andWhere('user.host IS NULL');
+ } else {
+ query.andWhere('user.host = :host', { host: opts.host });
}
+ }
- query
- .andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(q) }%` })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
+ this.queryService.generateVisibilityQuery(query, me);
+ if (me) this.queryService.generateMutedUserQuery(query, me);
+ if (me) this.queryService.generateBlockedUserQuery(query, me);
- if (opts.host) {
- if (opts.host === '.') {
- query.andWhere('user.host IS NULL');
- } else {
- query.andWhere('user.host = :host', { host: opts.host });
- }
- }
+ return query.limit(pagination.limit).getMany();
+ }
- this.queryService.generateVisibilityQuery(query, me);
- if (me) this.queryService.generateMutedUserQuery(query, me);
- if (me) this.queryService.generateBlockedUserQuery(query, me);
+ @bindThis
+ private async searchNoteByMeiliSearch(
+ q: string,
+ me: MiUser | null,
+ opts: SearchOpts,
+ pagination: SearchPagination,
+ ): Promise<MiNote[]> {
+ if (!this.meilisearch || !this.meilisearchNoteIndex) {
+ throw new Error('MeiliSearch is not available');
+ }
+
+ const filter: Q = {
+ op: 'and',
+ qs: [],
+ };
+ if (pagination.untilId) filter.qs.push({
+ op: '<',
+ k: 'createdAt',
+ v: this.idService.parse(pagination.untilId).date.getTime(),
+ });
+ if (pagination.sinceId) filter.qs.push({
+ op: '>',
+ k: 'createdAt',
+ v: this.idService.parse(pagination.sinceId).date.getTime(),
+ });
+ if (opts.userId) filter.qs.push({ op: '=', k: 'userId', v: opts.userId });
+ if (opts.channelId) filter.qs.push({ op: '=', k: 'channelId', v: opts.channelId });
+ if (opts.host) {
+ if (opts.host === '.') {
+ filter.qs.push({ op: 'is null', k: 'userHost' });
+ } else {
+ filter.qs.push({ op: '=', k: 'userHost', v: opts.host });
+ }
+ }
- return await query.limit(pagination.limit).getMany();
+ const res = await this.meilisearchNoteIndex.search(q, {
+ sort: ['createdAt:desc'],
+ matchingStrategy: 'all',
+ attributesToRetrieve: ['id', 'createdAt'],
+ filter: compileQuery(filter),
+ limit: pagination.limit,
+ });
+ if (res.hits.length === 0) {
+ return [];
}
+
+ const [
+ userIdsWhoMeMuting,
+ userIdsWhoBlockingMe,
+ ] = me
+ ? await Promise.all([
+ this.cacheService.userMutingsCache.fetch(me.id),
+ this.cacheService.userBlockedCache.fetch(me.id),
+ ])
+ : [new Set<string>(), new Set<string>()];
+ const notes = (await this.notesRepository.findBy({
+ id: In(res.hits.map(x => x.id)),
+ })).filter(note => {
+ if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
+ if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
+ return true;
+ });
+
+ return notes.sort((a, b) => a.id > b.id ? -1 : 1);
}
}
diff --git a/packages/backend/src/core/SystemWebhookService.ts b/packages/backend/src/core/SystemWebhookService.ts
index de00169612..8239490adc 100644
--- a/packages/backend/src/core/SystemWebhookService.ts
+++ b/packages/backend/src/core/SystemWebhookService.ts
@@ -50,7 +50,6 @@ export type SystemWebhookPayload<T extends SystemWebhookEventType> =
@Injectable()
export class SystemWebhookService implements OnApplicationShutdown {
- private logger: Logger;
private activeSystemWebhooksFetched = false;
private activeSystemWebhooks: MiSystemWebhook[] = [];
@@ -62,11 +61,9 @@ export class SystemWebhookService implements OnApplicationShutdown {
private idService: IdService,
private queueService: QueueService,
private moderationLogService: ModerationLogService,
- private loggerService: LoggerService,
private globalEventService: GlobalEventService,
) {
this.redisForSub.on('message', this.onMessage);
- this.logger = this.loggerService.getLogger('webhook');
}
@bindThis
@@ -193,28 +190,24 @@ export class SystemWebhookService implements OnApplicationShutdown {
/**
* SystemWebhook をWebhook配送キューに追加する
* @see QueueService.systemWebhookDeliver
- * // TODO: contentの型を厳格化する
*/
@bindThis
public async enqueueSystemWebhook<T extends SystemWebhookEventType>(
- webhook: MiSystemWebhook | MiSystemWebhook['id'],
type: T,
content: SystemWebhookPayload<T>,
+ opts?: {
+ excludes?: MiSystemWebhook['id'][];
+ },
) {
- const webhookEntity = typeof webhook === 'string'
- ? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook)
- : webhook;
- if (!webhookEntity || !webhookEntity.isActive) {
- this.logger.info(`SystemWebhook is not active or not found : ${webhook}`);
- return;
- }
-
- if (!webhookEntity.on.includes(type)) {
- this.logger.info(`SystemWebhook ${webhookEntity.id} is not listening to ${type}`);
- return;
- }
-
- return this.queueService.systemWebhookDeliver(webhookEntity, type, content);
+ const webhooks = await this.fetchActiveSystemWebhooks()
+ .then(webhooks => {
+ return webhooks.filter(webhook => !opts?.excludes?.includes(webhook.id) && webhook.on.includes(type));
+ });
+ return Promise.all(
+ webhooks.map(webhook => {
+ return this.queueService.systemWebhookDeliver(webhook, type, content);
+ }),
+ );
}
@bindThis
diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts
index 2f1310b8ef..8da1bb2092 100644
--- a/packages/backend/src/core/UserBlockingService.ts
+++ b/packages/backend/src/core/UserBlockingService.ts
@@ -118,13 +118,7 @@ export class UserBlockingService implements OnModuleInit {
schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'unfollow', {
- user: packed,
- });
- }
+ this.webhookService.enqueueUserWebhook(follower.id, 'unfollow', { user: packed });
});
}
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index 8963003057..b98ca97ec9 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -333,13 +333,7 @@ export class UserFollowingService implements OnModuleInit {
schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'follow', packed);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'follow', {
- user: packed,
- });
- }
+ this.webhookService.enqueueUserWebhook(follower.id, 'follow', { user: packed });
});
}
@@ -347,13 +341,7 @@ export class UserFollowingService implements OnModuleInit {
if (this.userEntityService.isLocalUser(followee)) {
this.userEntityService.pack(follower.id, followee).then(async packed => {
this.globalEventService.publishMainStream(followee.id, 'followed', packed);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === followee.id && x.on.includes('followed'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'followed', {
- user: packed,
- });
- }
+ this.webhookService.enqueueUserWebhook(followee.id, 'followed', { user: packed });
});
// 通知を作成
@@ -400,13 +388,7 @@ export class UserFollowingService implements OnModuleInit {
schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'unfollow', {
- user: packed,
- });
- }
+ this.webhookService.enqueueUserWebhook(follower.id, 'unfollow', { user: packed });
});
}
@@ -744,13 +726,7 @@ export class UserFollowingService implements OnModuleInit {
});
this.globalEventService.publishMainStream(follower.id, 'unfollow', packedFollowee);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow'));
- for (const webhook of webhooks) {
- this.queueService.userWebhookDeliver(webhook, 'unfollow', {
- user: packedFollowee,
- });
- }
+ this.webhookService.enqueueUserWebhook(follower.id, 'unfollow', { user: packedFollowee });
}
@bindThis
diff --git a/packages/backend/src/core/UserService.ts b/packages/backend/src/core/UserService.ts
index 9b1961c631..1f471513f3 100644
--- a/packages/backend/src/core/UserService.ts
+++ b/packages/backend/src/core/UserService.ts
@@ -63,13 +63,6 @@ export class UserService {
@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,
- );
- }
+ return this.systemWebhookService.enqueueSystemWebhook(type, packedUser);
}
}
diff --git a/packages/backend/src/core/UserWebhookService.ts b/packages/backend/src/core/UserWebhookService.ts
index 7117a3d7fa..b1728671ae 100644
--- a/packages/backend/src/core/UserWebhookService.ts
+++ b/packages/backend/src/core/UserWebhookService.ts
@@ -5,13 +5,14 @@
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
-import { type WebhooksRepository } from '@/models/_.js';
+import { MiUser, type WebhooksRepository } from '@/models/_.js';
import { MiWebhook, WebhookEventTypes } from '@/models/Webhook.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { GlobalEvents } from '@/core/GlobalEventService.js';
-import type { OnApplicationShutdown } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
+import { QueueService } from '@/core/QueueService.js';
+import type { OnApplicationShutdown } from '@nestjs/common';
export type UserWebhookPayload<T extends WebhookEventTypes> =
T extends 'note' | 'reply' | 'renote' |'mention' ? {
@@ -34,6 +35,7 @@ export class UserWebhookService implements OnApplicationShutdown {
private redisForSub: Redis.Redis,
@Inject(DI.webhooksRepository)
private webhooksRepository: WebhooksRepository,
+ private queueService: QueueService,
) {
this.redisForSub.on('message', this.onMessage);
}
@@ -75,6 +77,25 @@ export class UserWebhookService implements OnApplicationShutdown {
return query.getMany();
}
+ /**
+ * UserWebhook をWebhook配送キューに追加する
+ * @see QueueService.userWebhookDeliver
+ */
+ @bindThis
+ public async enqueueUserWebhook<T extends WebhookEventTypes>(
+ userId: MiUser['id'],
+ type: T,
+ content: UserWebhookPayload<T>,
+ ) {
+ const webhooks = await this.getActiveWebhooks()
+ .then(webhooks => webhooks.filter(webhook => webhook.userId === userId && webhook.on.includes(type)));
+ return Promise.all(
+ webhooks.map(webhook => {
+ return this.queueService.userWebhookDeliver(webhook, type, content);
+ }),
+ );
+ }
+
@bindThis
private async onMessage(_: string, data: string): Promise<void> {
const obj = JSON.parse(data);
diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts
index 9a2ba72ed3..fcb750d3bf 100644
--- a/packages/backend/src/core/UtilityService.ts
+++ b/packages/backend/src/core/UtilityService.ts
@@ -3,8 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { URL } from 'node:url';
-import { toASCII } from 'punycode';
+import { URL, domainToASCII } from 'node:url';
import { Inject, Injectable } from '@nestjs/common';
import RE2 from 're2';
import { DI } from '@/di-symbols.js';
@@ -106,13 +105,13 @@ export class UtilityService {
@bindThis
public toPuny(host: string): string {
- return toASCII(host.toLowerCase());
+ return domainToASCII(host.toLowerCase());
}
@bindThis
public toPunyNullable(host: string | null | undefined): string | null {
if (host == null) return null;
- return toASCII(host.toLowerCase());
+ return domainToASCII(host.toLowerCase());
}
@bindThis
diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts
index ad53192f18..ed75e4f467 100644
--- a/packages/backend/src/core/WebAuthnService.ts
+++ b/packages/backend/src/core/WebAuthnService.ts
@@ -189,14 +189,12 @@ export class WebAuthnService {
*/
@bindThis
public async verifySignInWithPasskeyAuthentication(context: string, response: AuthenticationResponseJSON): Promise<MiUser['id'] | null> {
- const challenge = await this.redisClient.get(`webauthn:challenge:${context}`);
+ const challenge = await this.redisClient.getdel(`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,
});
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index 5617a29bab..9148095067 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -183,6 +183,9 @@ export class ApRendererService {
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl,
},
+ _misskey_license: {
+ freeText: emoji.license
+ },
};
}
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index b0b35274ea..52cc569140 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -20,6 +20,7 @@ import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js';
import { ApRequestService } from './ApRequestService.js';
import type { IObject, ICollection, IOrderedCollection } from './type.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
export class Resolver {
private history: Set<string>;
@@ -66,7 +67,7 @@ export class Resolver {
if (isCollectionOrOrderedCollection(collection)) {
return collection;
} else {
- throw new Error(`unrecognized collection type: ${collection.type}`);
+ throw new IdentifiableError('f100eccf-f347-43fb-9b45-96a0831fb635', `unrecognized collection type: ${collection.type}`);
}
}
@@ -80,15 +81,15 @@ export class Resolver {
// URLs with fragment parts cannot be resolved correctly because
// the fragment part does not get transmitted over HTTP(S).
// Avoid strange behaviour by not trying to resolve these at all.
- throw new Error(`cannot resolve URL with fragment: ${value}`);
+ throw new IdentifiableError('b94fd5b1-0e3b-4678-9df2-dad4cd515ab2', `cannot resolve URL with fragment: ${value}`);
}
if (this.history.has(value)) {
- throw new Error('cannot resolve already resolved one');
+ throw new IdentifiableError('0dc86cf6-7cd6-4e56-b1e6-5903d62d7ea5', 'cannot resolve already resolved one');
}
if (this.history.size > this.recursionLimit) {
- throw new Error(`hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
+ throw new IdentifiableError('d592da9f-822f-4d91-83d7-4ceefabcf3d2', `hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
}
this.history.add(value);
@@ -99,7 +100,7 @@ export class Resolver {
}
if (!this.utilityService.isFederationAllowedHost(host)) {
- throw new Error('Instance is blocked');
+ throw new IdentifiableError('09d79f9e-64f1-4316-9cfa-e75c4d091574', 'Instance is blocked');
}
if (this.config.signToActivityPubGet && !this.user) {
@@ -115,7 +116,7 @@ export class Resolver {
!(object['@context'] as unknown[]).includes('https://www.w3.org/ns/activitystreams') :
object['@context'] !== 'https://www.w3.org/ns/activitystreams'
) {
- throw new Error('invalid response');
+ throw new IdentifiableError('72180409-793c-4973-868e-5a118eb5519b', 'invalid response');
}
// HttpRequestService / ApRequestService have already checked that
@@ -123,11 +124,11 @@ export class Resolver {
// object after redirects; here we double-check that no redirects
// bounced between hosts
if (object.id == null) {
- throw new Error('invalid AP object: missing id');
+ throw new IdentifiableError('ad2dc287-75c1-44c4-839d-3d2e64576675', 'invalid AP object: missing id');
}
if (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value)) {
- throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
+ throw new IdentifiableError('fd93c2fa-69a8-440f-880b-bf178e0ec877', `invalid AP object ${value}: id ${object.id} has different host`);
}
return object;
@@ -136,7 +137,7 @@ export class Resolver {
@bindThis
private resolveLocal(url: string): Promise<IObject> {
const parsed = this.apDbResolverService.parseUri(url);
- if (!parsed.local) throw new Error('resolveLocal: not local');
+ if (!parsed.local) throw new IdentifiableError('02b40cd0-fa92-4b0c-acc9-fb2ada952ab8', 'resolveLocal: not local');
switch (parsed.type) {
case 'notes':
@@ -165,7 +166,7 @@ export class Resolver {
case 'follows':
return this.followRequestsRepository.findOneBy({ id: parsed.id })
.then(async followRequest => {
- if (followRequest == null) throw new Error('resolveLocal: invalid follow request ID');
+ if (followRequest == null) throw new IdentifiableError('a9d946e5-d276-47f8-95fb-f04230289bb0', 'resolveLocal: invalid follow request ID');
const [follower, followee] = await Promise.all([
this.usersRepository.findOneBy({
id: followRequest.followerId,
@@ -177,12 +178,12 @@ export class Resolver {
}),
]);
if (follower == null || followee == null) {
- throw new Error('resolveLocal: follower or followee does not exist');
+ throw new IdentifiableError('06ae3170-1796-4d93-a697-2611ea6d83b6', 'resolveLocal: follower or followee does not exist');
}
return this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url));
});
default:
- throw new Error(`resolveLocal: type ${parsed.type} unhandled`);
+ throw new IdentifiableError('7a5d2fc0-94bc-4db6-b8b8-1bf24a2e23d0', `resolveLocal: type ${parsed.type} unhandled`);
}
}
}
diff --git a/packages/backend/src/core/activitypub/misc/check-against-url.ts b/packages/backend/src/core/activitypub/misc/check-against-url.ts
index 78ba891a2e..d679bd8180 100644
--- a/packages/backend/src/core/activitypub/misc/check-against-url.ts
+++ b/packages/backend/src/core/activitypub/misc/check-against-url.ts
@@ -5,13 +5,15 @@
import type { IObject } from '../type.js';
export function assertActivityMatchesUrls(activity: IObject, urls: string[]) {
- const idOk = activity.id !== undefined && urls.includes(activity.id);
+ const hosts = urls.map(it => new URL(it).host);
+
+ const idOk = activity.id !== undefined && hosts.includes(new URL(activity.id).host);
// technically `activity.url` could be an `ApObject = IObject |
// string | (IObject | string)[]`, but if it's a complicated thing
// and the `activity.id` doesn't match, I think we're fine
// rejecting the activity
- const urlOk = typeof(activity.url) === 'string' && urls.includes(activity.url);
+ const urlOk = typeof(activity.url) === 'string' && hosts.includes(new URL(activity.url).host);
if (!idOk && !urlOk) {
throw new Error(`bad Activity: neither id(${activity?.id}) nor url(${activity?.url}) match location(${urls})`);
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 94cb0785cb..6611e4b7f9 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -558,6 +558,11 @@ const extension_context_definition = {
'_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents',
'_misskey_makeNotesFollowersOnlyBefore': 'misskey:_misskey_makeNotesFollowersOnlyBefore',
'_misskey_makeNotesHiddenBefore': 'misskey:_misskey_makeNotesHiddenBefore',
+ '_misskey_license': 'misskey:_misskey_license',
+ 'freeText': {
+ '@id': 'misskey:freeText',
+ '@type': 'schema:text',
+ },
'isCat': 'misskey:isCat',
// vcard
vcard: 'http://www.w3.org/2006/vcard/ns#',
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index eb2e771a38..8abacd293f 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -154,14 +154,8 @@ export class ApNoteService {
const url = getOneApHrefNullable(note.url);
- if (url != null) {
- if (!checkHttps(url)) {
- throw new Error('unexpected schema of note url: ' + url);
- }
-
- if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) {
- throw new Error(`note url & uri host mismatch: note url: ${url}, note uri: ${note.id}`);
- }
+ if (url && !checkHttps(url)) {
+ throw new Error('unexpected schema of note url: ' + url);
}
this.logger.info(`Creating the Note: ${note.id}`);
@@ -414,6 +408,8 @@ export class ApNoteService {
originalUrl: tag.icon.url,
publicUrl: tag.icon.url,
updatedAt: new Date(),
+ // _misskey_license が存在しなければ `null`
+ license: (tag._misskey_license?.freeText ?? null)
});
const emoji = await this.emojisRepository.findOneBy({ host, name });
@@ -435,6 +431,8 @@ export class ApNoteService {
publicUrl: tag.icon.url,
updatedAt: new Date(),
aliases: [],
+ // _misskey_license が存在しなければ `null`
+ license: (tag._misskey_license?.freeText ?? null)
});
}));
}
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 8590861ca0..6019906add 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -157,8 +157,12 @@ export class ApPersonService implements OnModuleInit {
const sharedInboxObject = x.sharedInbox ?? (x.endpoints ? x.endpoints.sharedInbox : undefined);
if (sharedInboxObject != null) {
const sharedInbox = getApId(sharedInboxObject);
- if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && this.utilityService.punyHost(sharedInbox) === expectHost)) {
- throw new Error('invalid Actor: wrong shared inbox');
+ if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && new URL(sharedInbox).host === expectHost)) {
+ this.logger.warn(`invalid Actor: skipping wrong shared inbox, expected host: ${expectHost}, actual URL: ${sharedInbox}`);
+ x.sharedInbox = undefined;
+ if (x.endpoints?.sharedInbox) {
+ x.endpoints.sharedInbox = undefined;
+ }
}
}
@@ -257,7 +261,7 @@ export class ApPersonService implements OnModuleInit {
if (Array.isArray(img)) {
img = img.find(item => item && item.url) ?? null;
}
-
+
// if we have an explicitly missing image, return an
// explicitly-null set of values
if ((img == null) || (typeof img === 'object' && img.url == null)) {
@@ -344,14 +348,8 @@ export class ApPersonService implements OnModuleInit {
throw new Error('Refusing to create person without id');
}
- if (url != null) {
- if (!checkHttps(url)) {
- throw new Error('unexpected schema of person url: ' + url);
- }
-
- if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) {
- throw new Error(`person url <> uri host mismatch: ${url} <> ${person.id}`);
- }
+ if (url && !checkHttps(url)) {
+ throw new Error('unexpected schema of person url: ' + url);
}
// Create user
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 7496315f09..72732b01df 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -242,6 +242,11 @@ export interface IApEmoji extends IObject {
type: 'Emoji';
name: string;
updated: string;
+ // Misskey拡張。後方互換性のためにoptional。
+ // 将来の拡張性を考慮してobjectにしている
+ _misskey_license?: {
+ freeText: string | null;
+ };
}
export const isEmoji = (object: IObject): object is IApEmoji =>
diff --git a/packages/backend/src/core/chart/ChartManagementService.ts b/packages/backend/src/core/chart/ChartManagementService.ts
index 79681370a1..f04c561063 100644
--- a/packages/backend/src/core/chart/ChartManagementService.ts
+++ b/packages/backend/src/core/chart/ChartManagementService.ts
@@ -58,9 +58,9 @@ export class ChartManagementService implements OnApplicationShutdown {
@bindThis
public async start() {
// 20分おきにメモリ情報をDBに書き込み
- this.saveIntervalId = setInterval(() => {
+ this.saveIntervalId = setInterval(async () => {
for (const chart of this.charts) {
- chart.save();
+ await chart.save();
}
}, 1000 * 60 * 20);
}
@@ -69,9 +69,9 @@ export class ChartManagementService implements OnApplicationShutdown {
public async dispose(): Promise<void> {
clearInterval(this.saveIntervalId);
if (process.env.NODE_ENV !== 'test') {
- await Promise.all(
- this.charts.map(chart => chart.save()),
- );
+ for (const chart of this.charts) {
+ await chart.save();
+ }
}
}
diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts
index 841bd731c0..490d3f2511 100644
--- a/packages/backend/src/core/entities/EmojiEntityService.ts
+++ b/packages/backend/src/core/entities/EmojiEntityService.ts
@@ -4,10 +4,10 @@
*/
import { Inject, Injectable } from '@nestjs/common';
+import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
-import type { EmojisRepository } from '@/models/_.js';
+import type { EmojisRepository, MiRole, RolesRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
-import type { } from '@/models/Blocking.js';
import type { MiEmoji } from '@/models/Emoji.js';
import { bindThis } from '@/decorators.js';
@@ -16,6 +16,8 @@ export class EmojiEntityService {
constructor(
@Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository,
+ @Inject(DI.rolesRepository)
+ private rolesRepository: RolesRepository,
) {
}
@@ -68,8 +70,90 @@ export class EmojiEntityService {
@bindThis
public packDetailedMany(
emojis: any[],
- ) {
+ ): Promise<Packed<'EmojiDetailed'>[]> {
return Promise.all(emojis.map(x => this.packDetailed(x)));
}
+
+ @bindThis
+ public async packDetailedAdmin(
+ src: MiEmoji['id'] | MiEmoji,
+ hint?: {
+ roles?: Map<MiRole['id'], MiRole>
+ },
+ ): Promise<Packed<'EmojiDetailedAdmin'>> {
+ const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
+
+ const roles = Array.of<MiRole>();
+ if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0) {
+ if (hint?.roles) {
+ const hintRoles = hint.roles;
+ roles.push(
+ ...emoji.roleIdsThatCanBeUsedThisEmojiAsReaction
+ .filter(x => hintRoles.has(x))
+ .map(x => hintRoles.get(x)!),
+ );
+ } else {
+ roles.push(
+ ...await this.rolesRepository.findBy({ id: In(emoji.roleIdsThatCanBeUsedThisEmojiAsReaction) }),
+ );
+ }
+
+ roles.sort((a, b) => {
+ if (a.displayOrder !== b.displayOrder) {
+ return b.displayOrder - a.displayOrder;
+ }
+
+ return a.id.localeCompare(b.id);
+ });
+ }
+
+ return {
+ id: emoji.id,
+ updatedAt: emoji.updatedAt?.toISOString() ?? null,
+ name: emoji.name,
+ host: emoji.host,
+ uri: emoji.uri,
+ type: emoji.type,
+ aliases: emoji.aliases,
+ category: emoji.category,
+ publicUrl: emoji.publicUrl,
+ originalUrl: emoji.originalUrl,
+ license: emoji.license,
+ localOnly: emoji.localOnly,
+ isSensitive: emoji.isSensitive,
+ roleIdsThatCanBeUsedThisEmojiAsReaction: roles.map(it => ({ id: it.id, name: it.name })),
+ };
+ }
+
+ @bindThis
+ public async packDetailedAdminMany(
+ emojis: MiEmoji['id'][] | MiEmoji[],
+ hint?: {
+ roles?: Map<MiRole['id'], MiRole>
+ },
+ ): Promise<Packed<'EmojiDetailedAdmin'>[]> {
+ // IDのみの要素をピックアップし、DBからレコードを取り出して他の値を補完する
+ const emojiEntities = emojis.filter(x => typeof x === 'object') as MiEmoji[];
+ const emojiIdOnlyList = emojis.filter(x => typeof x === 'string') as string[];
+ if (emojiIdOnlyList.length > 0) {
+ emojiEntities.push(...await this.emojisRepository.findBy({ id: In(emojiIdOnlyList) }));
+ }
+
+ // 特定ロール専用の絵文字である場合、そのロール情報をあらかじめまとめて取得しておく(pack側で都度取得も出来るが負荷が高いので)
+ let hintRoles: Map<MiRole['id'], MiRole>;
+ if (hint?.roles) {
+ hintRoles = hint.roles;
+ } else {
+ const roles = Array.of<MiRole>();
+ const roleIds = [...new Set(emojiEntities.flatMap(x => x.roleIdsThatCanBeUsedThisEmojiAsReaction))];
+ if (roleIds.length > 0) {
+ roles.push(...await this.rolesRepository.findBy({ id: In(roleIds) }));
+ }
+
+ hintRoles = new Map(roles.map(x => [x.id, x]));
+ }
+
+ return Promise.all(emojis.map(x => this.packDetailedAdmin(x, { roles: hintRoles })));
+ }
}
diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts
index 409dca3426..ec0b5360f4 100644
--- a/packages/backend/src/core/entities/MetaEntityService.ts
+++ b/packages/backend/src/core/entities/MetaEntityService.ts
@@ -132,6 +132,7 @@ export class MetaEntityService {
enableUrlPreview: instance.urlPreviewEnabled,
noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local',
maxFileSize: this.config.maxFileSize,
+ federation: this.meta.federation,
};
return packed;
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 96cc6b028e..97f1c3d739 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -102,8 +102,7 @@ export class NoteEntityService implements OnModuleInit {
}
@bindThis
- private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<void> {
- // FIXME: このvisibility変更処理が当関数にあるのは若干不自然かもしれない(関数名を treatVisibility とかに変える手もある)
+ private treatVisibility(packedNote: Packed<'Note'>): Packed<'Note'>['visibility'] {
if (packedNote.visibility === 'public' || packedNote.visibility === 'home') {
const followersOnlyBefore = packedNote.user.makeNotesFollowersOnlyBefore;
if ((followersOnlyBefore != null)
@@ -115,7 +114,11 @@ export class NoteEntityService implements OnModuleInit {
packedNote.visibility = 'followers';
}
}
+ return packedNote.visibility;
+ }
+ @bindThis
+ private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<void> {
if (meId === packedNote.userId) return;
// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
@@ -458,6 +461,8 @@ export class NoteEntityService implements OnModuleInit {
} : {}),
});
+ this.treatVisibility(packed);
+
if (!opts.skipHide) {
await this.hideNote(packed, meId);
}
diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts
index 040e36228c..f612591eda 100644
--- a/packages/backend/src/misc/json-schema.ts
+++ b/packages/backend/src/misc/json-schema.ts
@@ -33,7 +33,11 @@ import { packedClipSchema } from '@/models/json-schema/clip.js';
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
import { packedQueueCountSchema } from '@/models/json-schema/queue.js';
import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js';
-import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
+import {
+ packedEmojiDetailedAdminSchema,
+ packedEmojiDetailedSchema,
+ packedEmojiSimpleSchema,
+} from '@/models/json-schema/emoji.js';
import { packedFlashSchema } from '@/models/json-schema/flash.js';
import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js';
import { packedSigninSchema } from '@/models/json-schema/signin.js';
@@ -95,6 +99,7 @@ export const refs = {
GalleryPost: packedGalleryPostSchema,
EmojiSimple: packedEmojiSimpleSchema,
EmojiDetailed: packedEmojiDetailedSchema,
+ EmojiDetailedAdmin: packedEmojiDetailedAdminSchema,
Flash: packedFlashSchema,
Signin: packedSigninSchema,
RoleCondFormulaLogics: packedRoleCondFormulaLogicsSchema,
diff --git a/packages/backend/src/models/json-schema/emoji.ts b/packages/backend/src/models/json-schema/emoji.ts
index 62686ad5ae..3cd263fa37 100644
--- a/packages/backend/src/models/json-schema/emoji.ts
+++ b/packages/backend/src/models/json-schema/emoji.ts
@@ -104,3 +104,86 @@ export const packedEmojiDetailedSchema = {
},
},
} as const;
+
+export const packedEmojiDetailedAdminSchema = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'id',
+ optional: false, nullable: false,
+ },
+ updatedAt: {
+ type: 'string',
+ format: 'date-time',
+ optional: false, nullable: true,
+ },
+ name: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ host: {
+ type: 'string',
+ optional: false, nullable: true,
+ description: 'The local host is represented with `null`.',
+ },
+ publicUrl: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ originalUrl: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ uri: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ type: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ aliases: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'string',
+ format: 'id',
+ optional: false, nullable: false,
+ },
+ },
+ category: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ license: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ localOnly: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ isSensitive: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ roleIdsThatCanBeUsedThisEmojiAsReaction: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ optional: false, nullable: false,
+ },
+ name: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ },
+ },
+ },
+ },
+} as const;
diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts
index e3fd63464a..e7ae2ee8e5 100644
--- a/packages/backend/src/models/json-schema/meta.ts
+++ b/packages/backend/src/models/json-schema/meta.ts
@@ -261,6 +261,11 @@ export const packedMetaLiteSchema = {
type: 'number',
optional: false, nullable: false,
},
+ federation: {
+ type: 'string',
+ enum: ['all', 'specified', 'none'],
+ optional: false, nullable: false,
+ },
},
} as const;
diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts
index 251a03c303..d09240eba1 100644
--- a/packages/backend/src/postgres.ts
+++ b/packages/backend/src/postgres.ts
@@ -89,27 +89,65 @@ export const dbLogger = new MisskeyLogger('db');
const sqlLogger = dbLogger.createSubLogger('sql', 'gray');
+export type LoggerProps = {
+ disableQueryTruncation?: boolean;
+ enableQueryParamLogging?: boolean;
+}
+
+function highlightSql(sql: string) {
+ return highlight.highlight(sql, {
+ language: 'sql', ignoreIllegals: true,
+ });
+}
+
+function truncateSql(sql: string) {
+ return sql.length > 100 ? `${sql.substring(0, 100)}...` : sql;
+}
+
+function stringifyParameter(param: any) {
+ if (param instanceof Date) {
+ return param.toISOString();
+ } else {
+ return param;
+ }
+}
+
class MyCustomLogger implements Logger {
+ constructor(private props: LoggerProps = {}) {
+ }
+
+ @bindThis
+ private transformQueryLog(sql: string) {
+ let modded = sql;
+ if (!this.props.disableQueryTruncation) {
+ modded = truncateSql(modded);
+ }
+
+ return highlightSql(modded);
+ }
+
@bindThis
- private highlight(sql: string) {
- return highlight.highlight(sql, {
- language: 'sql', ignoreIllegals: true,
- });
+ private transformParameters(parameters?: any[]) {
+ if (this.props.enableQueryParamLogging && parameters && parameters.length > 0) {
+ return parameters.map(stringifyParameter);
+ }
+
+ return undefined;
}
@bindThis
public logQuery(query: string, parameters?: any[]) {
- sqlLogger.info(this.highlight(query).substring(0, 100));
+ sqlLogger.info(this.transformQueryLog(query), this.transformParameters(parameters));
}
@bindThis
public logQueryError(error: string, query: string, parameters?: any[]) {
- sqlLogger.error(this.highlight(query));
+ sqlLogger.error(this.transformQueryLog(query), this.transformParameters(parameters));
}
@bindThis
public logQuerySlow(time: number, query: string, parameters?: any[]) {
- sqlLogger.warn(this.highlight(query));
+ sqlLogger.warn(this.transformQueryLog(query), this.transformParameters(parameters));
}
@bindThis
@@ -247,7 +285,12 @@ export function createPostgresDataSource(config: Config) {
},
} : false,
logging: log,
- logger: log ? new MyCustomLogger() : undefined,
+ logger: log
+ ? new MyCustomLogger({
+ disableQueryTruncation: config.logging?.sql?.disableQueryTruncation,
+ enableQueryParamLogging: config.logging?.sql?.enableQueryParamLogging,
+ })
+ : undefined,
maxQueryExecutionTime: 300,
entities: entities,
migrations: ['../../migration/*.js'],
diff --git a/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts b/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts
index 87183cb342..2e84430e72 100644
--- a/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts
+++ b/packages/backend/src/queue/processors/CheckModeratorsActivityProcessorService.ts
@@ -231,15 +231,10 @@ export class CheckModeratorsActivityProcessorService {
// -- SystemWebhook
- const systemWebhooks = await this.systemWebhookService.fetchActiveSystemWebhooks()
- .then(it => it.filter(it => it.on.includes('inactiveModeratorsWarning')));
- for (const systemWebhook of systemWebhooks) {
- this.systemWebhookService.enqueueSystemWebhook(
- systemWebhook,
- 'inactiveModeratorsWarning',
- { remainingTime: remainingTime },
- );
- }
+ return this.systemWebhookService.enqueueSystemWebhook(
+ 'inactiveModeratorsWarning',
+ { remainingTime: remainingTime },
+ );
}
@bindThis
@@ -269,15 +264,10 @@ export class CheckModeratorsActivityProcessorService {
// -- SystemWebhook
- const systemWebhooks = await this.systemWebhookService.fetchActiveSystemWebhooks()
- .then(it => it.filter(it => it.on.includes('inactiveModeratorsInvitationOnlyChanged')));
- for (const systemWebhook of systemWebhooks) {
- this.systemWebhookService.enqueueSystemWebhook(
- systemWebhook,
- 'inactiveModeratorsInvitationOnlyChanged',
- {},
- );
- }
+ return this.systemWebhookService.enqueueSystemWebhook(
+ 'inactiveModeratorsInvitationOnlyChanged',
+ {},
+ );
}
@bindThis
diff --git a/packages/backend/src/queue/processors/CleanChartsProcessorService.ts b/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
index 110468801c..8c5faa8d07 100644
--- a/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
@@ -48,20 +48,19 @@ export class CleanChartsProcessorService {
public async process(): Promise<void> {
this.logger.info('Clean charts...');
- await Promise.all([
- this.federationChart.clean(),
- this.notesChart.clean(),
- this.usersChart.clean(),
- this.activeUsersChart.clean(),
- this.instanceChart.clean(),
- this.perUserNotesChart.clean(),
- this.perUserPvChart.clean(),
- this.driveChart.clean(),
- this.perUserReactionsChart.clean(),
- this.perUserFollowingChart.clean(),
- this.perUserDriveChart.clean(),
- this.apRequestChart.clean(),
- ]);
+ // DBへの同時接続を避けるためにPromise.allを使わずひとつずつ実行する
+ await this.federationChart.clean();
+ await this.notesChart.clean();
+ await this.usersChart.clean();
+ await this.activeUsersChart.clean();
+ await this.instanceChart.clean();
+ await this.perUserNotesChart.clean();
+ await this.perUserPvChart.clean();
+ await this.driveChart.clean();
+ await this.perUserReactionsChart.clean();
+ await this.perUserFollowingChart.clean();
+ await this.perUserDriveChart.clean();
+ await this.apRequestChart.clean();
this.logger.succ('All charts successfully cleaned.');
}
diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
index 9e1b8fee70..725e1c8ba2 100644
--- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
+++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts
@@ -87,6 +87,7 @@ export class ImportCustomEmojisProcessorService {
await this.emojisRepository.delete({
name: emojiInfo.name,
});
+
try {
const driveFile = await this.driveService.addFile({
user: null,
@@ -95,11 +96,13 @@ export class ImportCustomEmojisProcessorService {
force: true,
});
await this.customEmojiService.add({
+ originalUrl: driveFile.url,
+ publicUrl: driveFile.webpublicUrl ?? driveFile.url,
+ fileType: driveFile.webpublicType ?? driveFile.type,
name: emojiInfo.name,
category: emojiInfo.category,
host: null,
aliases: emojiInfo.aliases,
- driveFile,
license: emojiInfo.license,
isSensitive: emojiInfo.isSensitive,
localOnly: emojiInfo.localOnly,
diff --git a/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts b/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
index 570cdf9a75..0c47fdedb3 100644
--- a/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
@@ -29,13 +29,12 @@ export class ResyncChartsProcessorService {
public async process(): Promise<void> {
this.logger.info('Resync charts...');
+ // DBへの同時接続を避けるためにPromise.allを使わずひとつずつ実行する
// TODO: ユーザーごとのチャートも更新する
// TODO: インスタンスごとのチャートも更新する
- await Promise.all([
- this.driveChart.resync(),
- this.notesChart.resync(),
- this.usersChart.resync(),
- ]);
+ await this.driveChart.resync();
+ await this.notesChart.resync();
+ await this.usersChart.resync();
this.logger.succ('All charts successfully resynced.');
}
diff --git a/packages/backend/src/queue/processors/TickChartsProcessorService.ts b/packages/backend/src/queue/processors/TickChartsProcessorService.ts
index 93ec34162d..fc8856a271 100644
--- a/packages/backend/src/queue/processors/TickChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/TickChartsProcessorService.ts
@@ -48,20 +48,19 @@ export class TickChartsProcessorService {
public async process(): Promise<void> {
this.logger.info('Tick charts...');
- await Promise.all([
- this.federationChart.tick(false),
- this.notesChart.tick(false),
- this.usersChart.tick(false),
- this.activeUsersChart.tick(false),
- this.instanceChart.tick(false),
- this.perUserNotesChart.tick(false),
- this.perUserPvChart.tick(false),
- this.driveChart.tick(false),
- this.perUserReactionsChart.tick(false),
- this.perUserFollowingChart.tick(false),
- this.perUserDriveChart.tick(false),
- this.apRequestChart.tick(false),
- ]);
+ // DBへの同時接続を避けるためにPromise.allを使わずひとつずつ実行する
+ await this.federationChart.tick(false);
+ await this.notesChart.tick(false);
+ await this.usersChart.tick(false);
+ await this.activeUsersChart.tick(false);
+ await this.instanceChart.tick(false);
+ await this.perUserNotesChart.tick(false);
+ await this.perUserPvChart.tick(false);
+ await this.driveChart.tick(false);
+ await this.perUserReactionsChart.tick(false);
+ await this.perUserFollowingChart.tick(false);
+ await this.perUserDriveChart.tick(false);
+ await this.apRequestChart.tick(false);
this.logger.succ('All charts successfully ticked.');
}
diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts
index a4077a0547..5db919a149 100644
--- a/packages/backend/src/queue/types.ts
+++ b/packages/backend/src/queue/types.ts
@@ -6,9 +6,12 @@
import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiNote } from '@/models/Note.js';
+import type { SystemWebhookEventType } from '@/models/SystemWebhook.js';
import type { MiUser } from '@/models/User.js';
-import type { MiWebhook } from '@/models/Webhook.js';
+import type { MiWebhook, WebhookEventTypes } from '@/models/Webhook.js';
import type { IActivity } from '@/core/activitypub/type.js';
+import type { SystemWebhookPayload } from '@/core/SystemWebhookService.js';
+import type { UserWebhookPayload } from '@/core/UserWebhookService.js';
import type httpSignature from '@peertube/http-signature';
export type DeliverJobData = {
@@ -106,9 +109,9 @@ export type EndedPollNotificationJobData = {
noteId: MiNote['id'];
};
-export type SystemWebhookDeliverJobData = {
- type: string;
- content: unknown;
+export type SystemWebhookDeliverJobData<T extends SystemWebhookEventType = SystemWebhookEventType> = {
+ type: T;
+ content: SystemWebhookPayload<T>;
webhookId: MiWebhook['id'];
to: string;
secret: string;
@@ -116,9 +119,9 @@ export type SystemWebhookDeliverJobData = {
eventId: string;
};
-export type UserWebhookDeliverJobData = {
- type: string;
- content: unknown;
+export type UserWebhookDeliverJobData<T extends WebhookEventTypes = WebhookEventTypes> = {
+ type: T;
+ content: UserWebhookPayload<T>;
webhookId: MiWebhook['id'];
userId: MiUser['id'];
to: string;
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index f34f6583d3..8c4b13a40a 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -519,8 +519,8 @@ export class ActivityPubServerService {
},
deriveConstraint(request: IncomingMessage) {
const accepted = accepts(request).type(['html', ACTIVITY_JSON, LD_JSON]);
- const isAp = typeof accepted === 'string' && !accepted.match(/html/);
- return isAp ? 'ap' : 'html';
+ if (accepted === false) return null;
+ return accepted !== 'html' ? 'ap' : 'html';
},
});
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 5bb194313d..9cfb2f0ac0 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -6,778 +6,13 @@
import { Module } from '@nestjs/common';
import { CoreModule } from '@/core/CoreModule.js';
-import * as ep___admin_abuseReport_notificationRecipient_list from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js';
-import * as ep___admin_abuseReport_notificationRecipient_show from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js';
-import * as ep___admin_abuseReport_notificationRecipient_create from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js';
-import * as ep___admin_abuseReport_notificationRecipient_update from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js';
-import * as ep___admin_abuseReport_notificationRecipient_delete from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js';
-import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js';
-import * as ep___admin_meta from './endpoints/admin/meta.js';
-import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js';
-import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js';
-import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js';
-import * as ep___admin_ad_create from './endpoints/admin/ad/create.js';
-import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js';
-import * as ep___admin_ad_list from './endpoints/admin/ad/list.js';
-import * as ep___admin_ad_update from './endpoints/admin/ad/update.js';
-import * as ep___admin_announcements_create from './endpoints/admin/announcements/create.js';
-import * as ep___admin_announcements_delete from './endpoints/admin/announcements/delete.js';
-import * as ep___admin_announcements_list from './endpoints/admin/announcements/list.js';
-import * as ep___admin_announcements_update from './endpoints/admin/announcements/update.js';
-import * as ep___admin_avatarDecorations_create from './endpoints/admin/avatar-decorations/create.js';
-import * as ep___admin_avatarDecorations_delete from './endpoints/admin/avatar-decorations/delete.js';
-import * as ep___admin_avatarDecorations_list from './endpoints/admin/avatar-decorations/list.js';
-import * as ep___admin_avatarDecorations_update from './endpoints/admin/avatar-decorations/update.js';
-import * as ep___admin_deleteAllFilesOfAUser from './endpoints/admin/delete-all-files-of-a-user.js';
-import * as ep___admin_unsetUserAvatar from './endpoints/admin/unset-user-avatar.js';
-import * as ep___admin_unsetUserBanner from './endpoints/admin/unset-user-banner.js';
-import * as ep___admin_drive_cleanRemoteFiles from './endpoints/admin/drive/clean-remote-files.js';
-import * as ep___admin_drive_cleanup from './endpoints/admin/drive/cleanup.js';
-import * as ep___admin_drive_files from './endpoints/admin/drive/files.js';
-import * as ep___admin_drive_showFile from './endpoints/admin/drive/show-file.js';
-import * as ep___admin_emoji_addAliasesBulk from './endpoints/admin/emoji/add-aliases-bulk.js';
-import * as ep___admin_emoji_add from './endpoints/admin/emoji/add.js';
-import * as ep___admin_emoji_copy from './endpoints/admin/emoji/copy.js';
-import * as ep___admin_emoji_deleteBulk from './endpoints/admin/emoji/delete-bulk.js';
-import * as ep___admin_emoji_delete from './endpoints/admin/emoji/delete.js';
-import * as ep___admin_emoji_importZip from './endpoints/admin/emoji/import-zip.js';
-import * as ep___admin_emoji_listRemote from './endpoints/admin/emoji/list-remote.js';
-import * as ep___admin_emoji_list from './endpoints/admin/emoji/list.js';
-import * as ep___admin_emoji_removeAliasesBulk from './endpoints/admin/emoji/remove-aliases-bulk.js';
-import * as ep___admin_emoji_setAliasesBulk from './endpoints/admin/emoji/set-aliases-bulk.js';
-import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-category-bulk.js';
-import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js';
-import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js';
-import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js';
-import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js';
-import * as ep___admin_federation_removeAllFollowing from './endpoints/admin/federation/remove-all-following.js';
-import * as ep___admin_federation_updateInstance from './endpoints/admin/federation/update-instance.js';
-import * as ep___admin_getIndexStats from './endpoints/admin/get-index-stats.js';
-import * as ep___admin_getTableStats from './endpoints/admin/get-table-stats.js';
-import * as ep___admin_getUserIps from './endpoints/admin/get-user-ips.js';
-import * as ep___admin_invite_create from './endpoints/admin/invite/create.js';
-import * as ep___admin_invite_list from './endpoints/admin/invite/list.js';
-import * as ep___admin_promo_create from './endpoints/admin/promo/create.js';
-import * as ep___admin_queue_clear from './endpoints/admin/queue/clear.js';
-import * as ep___admin_queue_deliverDelayed from './endpoints/admin/queue/deliver-delayed.js';
-import * as ep___admin_queue_inboxDelayed from './endpoints/admin/queue/inbox-delayed.js';
-import * as ep___admin_queue_promote from './endpoints/admin/queue/promote.js';
-import * as ep___admin_queue_stats from './endpoints/admin/queue/stats.js';
-import * as ep___admin_relays_add from './endpoints/admin/relays/add.js';
-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';
-import * as ep___admin_showUser from './endpoints/admin/show-user.js';
-import * as ep___admin_showUsers from './endpoints/admin/show-users.js';
-import * as ep___admin_suspendUser from './endpoints/admin/suspend-user.js';
-import * as ep___admin_unsuspendUser from './endpoints/admin/unsuspend-user.js';
-import * as ep___admin_updateMeta from './endpoints/admin/update-meta.js';
-import * as ep___admin_deleteAccount from './endpoints/admin/delete-account.js';
-import * as ep___admin_updateUserNote from './endpoints/admin/update-user-note.js';
-import * as ep___admin_roles_create from './endpoints/admin/roles/create.js';
-import * as ep___admin_roles_delete from './endpoints/admin/roles/delete.js';
-import * as ep___admin_roles_list from './endpoints/admin/roles/list.js';
-import * as ep___admin_roles_show from './endpoints/admin/roles/show.js';
-import * as ep___admin_roles_update from './endpoints/admin/roles/update.js';
-import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js';
-import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js';
-import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js';
-import * as ep___admin_roles_users from './endpoints/admin/roles/users.js';
-import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js';
-import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js';
-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';
-import * as ep___antennas_delete from './endpoints/antennas/delete.js';
-import * as ep___antennas_list from './endpoints/antennas/list.js';
-import * as ep___antennas_notes from './endpoints/antennas/notes.js';
-import * as ep___antennas_show from './endpoints/antennas/show.js';
-import * as ep___antennas_update from './endpoints/antennas/update.js';
-import * as ep___ap_get from './endpoints/ap/get.js';
-import * as ep___ap_show from './endpoints/ap/show.js';
-import * as ep___app_create from './endpoints/app/create.js';
-import * as ep___app_show from './endpoints/app/show.js';
-import * as ep___auth_accept from './endpoints/auth/accept.js';
-import * as ep___auth_session_generate from './endpoints/auth/session/generate.js';
-import * as ep___auth_session_show from './endpoints/auth/session/show.js';
-import * as ep___auth_session_userkey from './endpoints/auth/session/userkey.js';
-import * as ep___blocking_create from './endpoints/blocking/create.js';
-import * as ep___blocking_delete from './endpoints/blocking/delete.js';
-import * as ep___blocking_list from './endpoints/blocking/list.js';
-import * as ep___channels_create from './endpoints/channels/create.js';
-import * as ep___channels_featured from './endpoints/channels/featured.js';
-import * as ep___channels_follow from './endpoints/channels/follow.js';
-import * as ep___channels_followed from './endpoints/channels/followed.js';
-import * as ep___channels_owned from './endpoints/channels/owned.js';
-import * as ep___channels_show from './endpoints/channels/show.js';
-import * as ep___channels_timeline from './endpoints/channels/timeline.js';
-import * as ep___channels_unfollow from './endpoints/channels/unfollow.js';
-import * as ep___channels_update from './endpoints/channels/update.js';
-import * as ep___channels_favorite from './endpoints/channels/favorite.js';
-import * as ep___channels_unfavorite from './endpoints/channels/unfavorite.js';
-import * as ep___channels_myFavorites from './endpoints/channels/my-favorites.js';
-import * as ep___channels_search from './endpoints/channels/search.js';
-import * as ep___charts_activeUsers from './endpoints/charts/active-users.js';
-import * as ep___charts_apRequest from './endpoints/charts/ap-request.js';
-import * as ep___charts_drive from './endpoints/charts/drive.js';
-import * as ep___charts_federation from './endpoints/charts/federation.js';
-import * as ep___charts_instance from './endpoints/charts/instance.js';
-import * as ep___charts_notes from './endpoints/charts/notes.js';
-import * as ep___charts_user_drive from './endpoints/charts/user/drive.js';
-import * as ep___charts_user_following from './endpoints/charts/user/following.js';
-import * as ep___charts_user_notes from './endpoints/charts/user/notes.js';
-import * as ep___charts_user_pv from './endpoints/charts/user/pv.js';
-import * as ep___charts_user_reactions from './endpoints/charts/user/reactions.js';
-import * as ep___charts_users from './endpoints/charts/users.js';
-import * as ep___clips_addNote from './endpoints/clips/add-note.js';
-import * as ep___clips_removeNote from './endpoints/clips/remove-note.js';
-import * as ep___clips_create from './endpoints/clips/create.js';
-import * as ep___clips_delete from './endpoints/clips/delete.js';
-import * as ep___clips_list from './endpoints/clips/list.js';
-import * as ep___clips_notes from './endpoints/clips/notes.js';
-import * as ep___clips_show from './endpoints/clips/show.js';
-import * as ep___clips_update from './endpoints/clips/update.js';
-import * as ep___clips_favorite from './endpoints/clips/favorite.js';
-import * as ep___clips_unfavorite from './endpoints/clips/unfavorite.js';
-import * as ep___clips_myFavorites from './endpoints/clips/my-favorites.js';
-import * as ep___drive from './endpoints/drive.js';
-import * as ep___drive_files from './endpoints/drive/files.js';
-import * as ep___drive_files_attachedNotes from './endpoints/drive/files/attached-notes.js';
-import * as ep___drive_files_checkExistence from './endpoints/drive/files/check-existence.js';
-import * as ep___drive_files_create from './endpoints/drive/files/create.js';
-import * as ep___drive_files_delete from './endpoints/drive/files/delete.js';
-import * as ep___drive_files_findByHash from './endpoints/drive/files/find-by-hash.js';
-import * as ep___drive_files_find from './endpoints/drive/files/find.js';
-import * as ep___drive_files_show from './endpoints/drive/files/show.js';
-import * as ep___drive_files_update from './endpoints/drive/files/update.js';
-import * as ep___drive_files_uploadFromUrl from './endpoints/drive/files/upload-from-url.js';
-import * as ep___drive_folders from './endpoints/drive/folders.js';
-import * as ep___drive_folders_create from './endpoints/drive/folders/create.js';
-import * as ep___drive_folders_delete from './endpoints/drive/folders/delete.js';
-import * as ep___drive_folders_find from './endpoints/drive/folders/find.js';
-import * as ep___drive_folders_show from './endpoints/drive/folders/show.js';
-import * as ep___drive_folders_update from './endpoints/drive/folders/update.js';
-import * as ep___drive_stream from './endpoints/drive/stream.js';
-import * as ep___emailAddress_available from './endpoints/email-address/available.js';
-import * as ep___endpoint from './endpoints/endpoint.js';
-import * as ep___endpoints from './endpoints/endpoints.js';
-import * as ep___exportCustomEmojis from './endpoints/export-custom-emojis.js';
-import * as ep___federation_followers from './endpoints/federation/followers.js';
-import * as ep___federation_following from './endpoints/federation/following.js';
-import * as ep___federation_instances from './endpoints/federation/instances.js';
-import * as ep___federation_showInstance from './endpoints/federation/show-instance.js';
-import * as ep___federation_updateRemoteUser from './endpoints/federation/update-remote-user.js';
-import * as ep___federation_users from './endpoints/federation/users.js';
-import * as ep___federation_stats from './endpoints/federation/stats.js';
-import * as ep___following_create from './endpoints/following/create.js';
-import * as ep___following_delete from './endpoints/following/delete.js';
-import * as ep___following_update from './endpoints/following/update.js';
-import * as ep___following_update_all from './endpoints/following/update-all.js';
-import * as ep___following_invalidate from './endpoints/following/invalidate.js';
-import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
-import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
-import * as ep___following_requests_list from './endpoints/following/requests/list.js';
-import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
-import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
-import * as ep___gallery_featured from './endpoints/gallery/featured.js';
-import * as ep___gallery_popular from './endpoints/gallery/popular.js';
-import * as ep___gallery_posts from './endpoints/gallery/posts.js';
-import * as ep___gallery_posts_create from './endpoints/gallery/posts/create.js';
-import * as ep___gallery_posts_delete from './endpoints/gallery/posts/delete.js';
-import * as ep___gallery_posts_like from './endpoints/gallery/posts/like.js';
-import * as ep___gallery_posts_show from './endpoints/gallery/posts/show.js';
-import * as ep___gallery_posts_unlike from './endpoints/gallery/posts/unlike.js';
-import * as ep___gallery_posts_update from './endpoints/gallery/posts/update.js';
-import * as ep___getOnlineUsersCount from './endpoints/get-online-users-count.js';
-import * as ep___getAvatarDecorations from './endpoints/get-avatar-decorations.js';
-import * as ep___hashtags_list from './endpoints/hashtags/list.js';
-import * as ep___hashtags_search from './endpoints/hashtags/search.js';
-import * as ep___hashtags_show from './endpoints/hashtags/show.js';
-import * as ep___hashtags_trend from './endpoints/hashtags/trend.js';
-import * as ep___hashtags_users from './endpoints/hashtags/users.js';
-import * as ep___i from './endpoints/i.js';
-import * as ep___i_2fa_done from './endpoints/i/2fa/done.js';
-import * as ep___i_2fa_keyDone from './endpoints/i/2fa/key-done.js';
-import * as ep___i_2fa_passwordLess from './endpoints/i/2fa/password-less.js';
-import * as ep___i_2fa_registerKey from './endpoints/i/2fa/register-key.js';
-import * as ep___i_2fa_register from './endpoints/i/2fa/register.js';
-import * as ep___i_2fa_updateKey from './endpoints/i/2fa/update-key.js';
-import * as ep___i_2fa_removeKey from './endpoints/i/2fa/remove-key.js';
-import * as ep___i_2fa_unregister from './endpoints/i/2fa/unregister.js';
-import * as ep___i_apps from './endpoints/i/apps.js';
-import * as ep___i_authorizedApps from './endpoints/i/authorized-apps.js';
-import * as ep___i_claimAchievement from './endpoints/i/claim-achievement.js';
-import * as ep___i_changePassword from './endpoints/i/change-password.js';
-import * as ep___i_deleteAccount from './endpoints/i/delete-account.js';
-import * as ep___i_exportBlocking from './endpoints/i/export-blocking.js';
-import * as ep___i_exportFollowing from './endpoints/i/export-following.js';
-import * as ep___i_exportMute from './endpoints/i/export-mute.js';
-import * as ep___i_exportNotes from './endpoints/i/export-notes.js';
-import * as ep___i_exportClips from './endpoints/i/export-clips.js';
-import * as ep___i_exportFavorites from './endpoints/i/export-favorites.js';
-import * as ep___i_exportUserLists from './endpoints/i/export-user-lists.js';
-import * as ep___i_exportAntennas from './endpoints/i/export-antennas.js';
-import * as ep___i_favorites from './endpoints/i/favorites.js';
-import * as ep___i_gallery_likes from './endpoints/i/gallery/likes.js';
-import * as ep___i_gallery_posts from './endpoints/i/gallery/posts.js';
-import * as ep___i_importBlocking from './endpoints/i/import-blocking.js';
-import * as ep___i_importFollowing from './endpoints/i/import-following.js';
-import * as ep___i_importMuting from './endpoints/i/import-muting.js';
-import * as ep___i_importUserLists from './endpoints/i/import-user-lists.js';
-import * as ep___i_importAntennas from './endpoints/i/import-antennas.js';
-import * as ep___i_notifications from './endpoints/i/notifications.js';
-import * as ep___i_notificationsGrouped from './endpoints/i/notifications-grouped.js';
-import * as ep___i_pageLikes from './endpoints/i/page-likes.js';
-import * as ep___i_pages from './endpoints/i/pages.js';
-import * as ep___i_pin from './endpoints/i/pin.js';
-import * as ep___i_readAllUnreadNotes from './endpoints/i/read-all-unread-notes.js';
-import * as ep___i_readAnnouncement from './endpoints/i/read-announcement.js';
-import * as ep___i_regenerateToken from './endpoints/i/regenerate-token.js';
-import * as ep___i_registry_getAll from './endpoints/i/registry/get-all.js';
-import * as ep___i_registry_getDetail from './endpoints/i/registry/get-detail.js';
-import * as ep___i_registry_get from './endpoints/i/registry/get.js';
-import * as ep___i_registry_keysWithType from './endpoints/i/registry/keys-with-type.js';
-import * as ep___i_registry_keys from './endpoints/i/registry/keys.js';
-import * as ep___i_registry_remove from './endpoints/i/registry/remove.js';
-import * as ep___i_registry_scopesWithDomain from './endpoints/i/registry/scopes-with-domain.js';
-import * as ep___i_registry_set from './endpoints/i/registry/set.js';
-import * as ep___i_revokeToken from './endpoints/i/revoke-token.js';
-import * as ep___i_signinHistory from './endpoints/i/signin-history.js';
-import * as ep___i_unpin from './endpoints/i/unpin.js';
-import * as ep___i_updateEmail from './endpoints/i/update-email.js';
-import * as ep___i_update from './endpoints/i/update.js';
-import * as ep___i_move from './endpoints/i/move.js';
-import * as ep___i_webhooks_create from './endpoints/i/webhooks/create.js';
-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';
-import * as ep___invite_limit from './endpoints/invite/limit.js';
-import * as ep___meta from './endpoints/meta.js';
-import * as ep___emojis from './endpoints/emojis.js';
-import * as ep___emoji from './endpoints/emoji.js';
-import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js';
-import * as ep___mute_create from './endpoints/mute/create.js';
-import * as ep___mute_delete from './endpoints/mute/delete.js';
-import * as ep___mute_list from './endpoints/mute/list.js';
-import * as ep___renoteMute_create from './endpoints/renote-mute/create.js';
-import * as ep___renoteMute_delete from './endpoints/renote-mute/delete.js';
-import * as ep___renoteMute_list from './endpoints/renote-mute/list.js';
-import * as ep___my_apps from './endpoints/my/apps.js';
-import * as ep___notes from './endpoints/notes.js';
-import * as ep___notes_children from './endpoints/notes/children.js';
-import * as ep___notes_clips from './endpoints/notes/clips.js';
-import * as ep___notes_conversation from './endpoints/notes/conversation.js';
-import * as ep___notes_create from './endpoints/notes/create.js';
-import * as ep___notes_delete from './endpoints/notes/delete.js';
-import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js';
-import * as ep___notes_favorites_delete from './endpoints/notes/favorites/delete.js';
-import * as ep___notes_featured from './endpoints/notes/featured.js';
-import * as ep___notes_globalTimeline from './endpoints/notes/global-timeline.js';
-import * as ep___notes_hybridTimeline from './endpoints/notes/hybrid-timeline.js';
-import * as ep___notes_localTimeline from './endpoints/notes/local-timeline.js';
-import * as ep___notes_mentions from './endpoints/notes/mentions.js';
-import * as ep___notes_polls_recommendation from './endpoints/notes/polls/recommendation.js';
-import * as ep___notes_polls_vote from './endpoints/notes/polls/vote.js';
-import * as ep___notes_reactions from './endpoints/notes/reactions.js';
-import * as ep___notes_reactions_create from './endpoints/notes/reactions/create.js';
-import * as ep___notes_reactions_delete from './endpoints/notes/reactions/delete.js';
-import * as ep___notes_renotes from './endpoints/notes/renotes.js';
-import * as ep___notes_replies from './endpoints/notes/replies.js';
-import * as ep___notes_searchByTag from './endpoints/notes/search-by-tag.js';
-import * as ep___notes_search from './endpoints/notes/search.js';
-import * as ep___notes_show from './endpoints/notes/show.js';
-import * as ep___notes_state from './endpoints/notes/state.js';
-import * as ep___notes_threadMuting_create from './endpoints/notes/thread-muting/create.js';
-import * as ep___notes_threadMuting_delete from './endpoints/notes/thread-muting/delete.js';
-import * as ep___notes_timeline from './endpoints/notes/timeline.js';
-import * as ep___notes_translate from './endpoints/notes/translate.js';
-import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
-import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
-import * as ep___notifications_create from './endpoints/notifications/create.js';
-import * as ep___notifications_flush from './endpoints/notifications/flush.js';
-import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js';
-import * as ep___notifications_testNotification from './endpoints/notifications/test-notification.js';
-import * as ep___pagePush from './endpoints/page-push.js';
-import * as ep___pages_create from './endpoints/pages/create.js';
-import * as ep___pages_delete from './endpoints/pages/delete.js';
-import * as ep___pages_featured from './endpoints/pages/featured.js';
-import * as ep___pages_like from './endpoints/pages/like.js';
-import * as ep___pages_show from './endpoints/pages/show.js';
-import * as ep___pages_unlike from './endpoints/pages/unlike.js';
-import * as ep___pages_update from './endpoints/pages/update.js';
-import * as ep___flash_create from './endpoints/flash/create.js';
-import * as ep___flash_delete from './endpoints/flash/delete.js';
-import * as ep___flash_featured from './endpoints/flash/featured.js';
-import * as ep___flash_like from './endpoints/flash/like.js';
-import * as ep___flash_show from './endpoints/flash/show.js';
-import * as ep___flash_unlike from './endpoints/flash/unlike.js';
-import * as ep___flash_update from './endpoints/flash/update.js';
-import * as ep___flash_my from './endpoints/flash/my.js';
-import * as ep___flash_myLikes from './endpoints/flash/my-likes.js';
-import * as ep___ping from './endpoints/ping.js';
-import * as ep___pinnedUsers from './endpoints/pinned-users.js';
-import * as ep___promo_read from './endpoints/promo/read.js';
-import * as ep___roles_list from './endpoints/roles/list.js';
-import * as ep___roles_show from './endpoints/roles/show.js';
-import * as ep___roles_users from './endpoints/roles/users.js';
-import * as ep___roles_notes from './endpoints/roles/notes.js';
-import * as ep___requestResetPassword from './endpoints/request-reset-password.js';
-import * as ep___resetDb from './endpoints/reset-db.js';
-import * as ep___resetPassword from './endpoints/reset-password.js';
-import * as ep___serverInfo from './endpoints/server-info.js';
-import * as ep___stats from './endpoints/stats.js';
-import * as ep___sw_show_registration from './endpoints/sw/show-registration.js';
-import * as ep___sw_update_registration from './endpoints/sw/update-registration.js';
-import * as ep___sw_register from './endpoints/sw/register.js';
-import * as ep___sw_unregister from './endpoints/sw/unregister.js';
-import * as ep___test from './endpoints/test.js';
-import * as ep___username_available from './endpoints/username/available.js';
-import * as ep___users from './endpoints/users.js';
-import * as ep___users_clips from './endpoints/users/clips.js';
-import * as ep___users_followers from './endpoints/users/followers.js';
-import * as ep___users_following from './endpoints/users/following.js';
-import * as ep___users_gallery_posts from './endpoints/users/gallery/posts.js';
-import * as ep___users_getFrequentlyRepliedUsers from './endpoints/users/get-frequently-replied-users.js';
-import * as ep___users_featuredNotes from './endpoints/users/featured-notes.js';
-import * as ep___users_lists_create from './endpoints/users/lists/create.js';
-import * as ep___users_lists_delete from './endpoints/users/lists/delete.js';
-import * as ep___users_lists_list from './endpoints/users/lists/list.js';
-import * as ep___users_lists_pull from './endpoints/users/lists/pull.js';
-import * as ep___users_lists_push from './endpoints/users/lists/push.js';
-import * as ep___users_lists_show from './endpoints/users/lists/show.js';
-import * as ep___users_lists_update from './endpoints/users/lists/update.js';
-import * as ep___users_lists_favorite from './endpoints/users/lists/favorite.js';
-import * as ep___users_lists_unfavorite from './endpoints/users/lists/unfavorite.js';
-import * as ep___users_lists_createFromPublic from './endpoints/users/lists/create-from-public.js';
-import * as ep___users_lists_updateMembership from './endpoints/users/lists/update-membership.js';
-import * as ep___users_lists_getMemberships from './endpoints/users/lists/get-memberships.js';
-import * as ep___users_notes from './endpoints/users/notes.js';
-import * as ep___users_pages from './endpoints/users/pages.js';
-import * as ep___users_flashs from './endpoints/users/flashs.js';
-import * as ep___users_reactions from './endpoints/users/reactions.js';
-import * as ep___users_recommendation from './endpoints/users/recommendation.js';
-import * as ep___users_relation from './endpoints/users/relation.js';
-import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js';
-import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js';
-import * as ep___users_search from './endpoints/users/search.js';
-import * as ep___users_show from './endpoints/users/show.js';
-import * as ep___users_achievements from './endpoints/users/achievements.js';
-import * as ep___users_updateMemo from './endpoints/users/update-memo.js';
-import * as ep___fetchRss from './endpoints/fetch-rss.js';
-import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js';
-import * as ep___retention from './endpoints/retention.js';
-import * as ep___bubbleGame_register from './endpoints/bubble-game/register.js';
-import * as ep___bubbleGame_ranking from './endpoints/bubble-game/ranking.js';
-import * as ep___reversi_cancelMatch from './endpoints/reversi/cancel-match.js';
-import * as ep___reversi_games from './endpoints/reversi/games.js';
-import * as ep___reversi_match from './endpoints/reversi/match.js';
-import * as ep___reversi_invitations from './endpoints/reversi/invitations.js';
-import * as ep___reversi_showGame from './endpoints/reversi/show-game.js';
-import * as ep___reversi_surrender from './endpoints/reversi/surrender.js';
-import * as ep___reversi_verify from './endpoints/reversi/verify.js';
+import * as endpointsObject from './endpoint-list.js';
import { GetterService } from './GetterService.js';
import { ApiLoggerService } from './ApiLoggerService.js';
import type { Provider } from '@nestjs/common';
-const $admin_meta: Provider = { provide: 'ep:admin/meta', useClass: ep___admin_meta.default };
-const $admin_abuseUserReports: Provider = { provide: 'ep:admin/abuse-user-reports', useClass: ep___admin_abuseUserReports.default };
-const $admin_abuseReport_notificationRecipient_list: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/list', useClass: ep___admin_abuseReport_notificationRecipient_list.default };
-const $admin_abuseReport_notificationRecipient_show: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/show', useClass: ep___admin_abuseReport_notificationRecipient_show.default };
-const $admin_abuseReport_notificationRecipient_create: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/create', useClass: ep___admin_abuseReport_notificationRecipient_create.default };
-const $admin_abuseReport_notificationRecipient_update: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/update', useClass: ep___admin_abuseReport_notificationRecipient_update.default };
-const $admin_abuseReport_notificationRecipient_delete: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/delete', useClass: ep___admin_abuseReport_notificationRecipient_delete.default };
-const $admin_accounts_create: Provider = { provide: 'ep:admin/accounts/create', useClass: ep___admin_accounts_create.default };
-const $admin_accounts_delete: Provider = { provide: 'ep:admin/accounts/delete', useClass: ep___admin_accounts_delete.default };
-const $admin_accounts_findByEmail: Provider = { provide: 'ep:admin/accounts/find-by-email', useClass: ep___admin_accounts_findByEmail.default };
-const $admin_ad_create: Provider = { provide: 'ep:admin/ad/create', useClass: ep___admin_ad_create.default };
-const $admin_ad_delete: Provider = { provide: 'ep:admin/ad/delete', useClass: ep___admin_ad_delete.default };
-const $admin_ad_list: Provider = { provide: 'ep:admin/ad/list', useClass: ep___admin_ad_list.default };
-const $admin_ad_update: Provider = { provide: 'ep:admin/ad/update', useClass: ep___admin_ad_update.default };
-const $admin_announcements_create: Provider = { provide: 'ep:admin/announcements/create', useClass: ep___admin_announcements_create.default };
-const $admin_announcements_delete: Provider = { provide: 'ep:admin/announcements/delete', useClass: ep___admin_announcements_delete.default };
-const $admin_announcements_list: Provider = { provide: 'ep:admin/announcements/list', useClass: ep___admin_announcements_list.default };
-const $admin_announcements_update: Provider = { provide: 'ep:admin/announcements/update', useClass: ep___admin_announcements_update.default };
-const $admin_avatarDecorations_create: Provider = { provide: 'ep:admin/avatar-decorations/create', useClass: ep___admin_avatarDecorations_create.default };
-const $admin_avatarDecorations_delete: Provider = { provide: 'ep:admin/avatar-decorations/delete', useClass: ep___admin_avatarDecorations_delete.default };
-const $admin_avatarDecorations_list: Provider = { provide: 'ep:admin/avatar-decorations/list', useClass: ep___admin_avatarDecorations_list.default };
-const $admin_avatarDecorations_update: Provider = { provide: 'ep:admin/avatar-decorations/update', useClass: ep___admin_avatarDecorations_update.default };
-const $admin_deleteAllFilesOfAUser: Provider = { provide: 'ep:admin/delete-all-files-of-a-user', useClass: ep___admin_deleteAllFilesOfAUser.default };
-const $admin_unsetUserAvatar: Provider = { provide: 'ep:admin/unset-user-avatar', useClass: ep___admin_unsetUserAvatar.default };
-const $admin_unsetUserBanner: Provider = { provide: 'ep:admin/unset-user-banner', useClass: ep___admin_unsetUserBanner.default };
-const $admin_drive_cleanRemoteFiles: Provider = { provide: 'ep:admin/drive/clean-remote-files', useClass: ep___admin_drive_cleanRemoteFiles.default };
-const $admin_drive_cleanup: Provider = { provide: 'ep:admin/drive/cleanup', useClass: ep___admin_drive_cleanup.default };
-const $admin_drive_files: Provider = { provide: 'ep:admin/drive/files', useClass: ep___admin_drive_files.default };
-const $admin_drive_showFile: Provider = { provide: 'ep:admin/drive/show-file', useClass: ep___admin_drive_showFile.default };
-const $admin_emoji_addAliasesBulk: Provider = { provide: 'ep:admin/emoji/add-aliases-bulk', useClass: ep___admin_emoji_addAliasesBulk.default };
-const $admin_emoji_add: Provider = { provide: 'ep:admin/emoji/add', useClass: ep___admin_emoji_add.default };
-const $admin_emoji_copy: Provider = { provide: 'ep:admin/emoji/copy', useClass: ep___admin_emoji_copy.default };
-const $admin_emoji_deleteBulk: Provider = { provide: 'ep:admin/emoji/delete-bulk', useClass: ep___admin_emoji_deleteBulk.default };
-const $admin_emoji_delete: Provider = { provide: 'ep:admin/emoji/delete', useClass: ep___admin_emoji_delete.default };
-const $admin_emoji_importZip: Provider = { provide: 'ep:admin/emoji/import-zip', useClass: ep___admin_emoji_importZip.default };
-const $admin_emoji_listRemote: Provider = { provide: 'ep:admin/emoji/list-remote', useClass: ep___admin_emoji_listRemote.default };
-const $admin_emoji_list: Provider = { provide: 'ep:admin/emoji/list', useClass: ep___admin_emoji_list.default };
-const $admin_emoji_removeAliasesBulk: Provider = { provide: 'ep:admin/emoji/remove-aliases-bulk', useClass: ep___admin_emoji_removeAliasesBulk.default };
-const $admin_emoji_setAliasesBulk: Provider = { provide: 'ep:admin/emoji/set-aliases-bulk', useClass: ep___admin_emoji_setAliasesBulk.default };
-const $admin_emoji_setCategoryBulk: Provider = { provide: 'ep:admin/emoji/set-category-bulk', useClass: ep___admin_emoji_setCategoryBulk.default };
-const $admin_emoji_setLicenseBulk: Provider = { provide: 'ep:admin/emoji/set-license-bulk', useClass: ep___admin_emoji_setLicenseBulk.default };
-const $admin_emoji_update: Provider = { provide: 'ep:admin/emoji/update', useClass: ep___admin_emoji_update.default };
-const $admin_federation_deleteAllFiles: Provider = { provide: 'ep:admin/federation/delete-all-files', useClass: ep___admin_federation_deleteAllFiles.default };
-const $admin_federation_refreshRemoteInstanceMetadata: Provider = { provide: 'ep:admin/federation/refresh-remote-instance-metadata', useClass: ep___admin_federation_refreshRemoteInstanceMetadata.default };
-const $admin_federation_removeAllFollowing: Provider = { provide: 'ep:admin/federation/remove-all-following', useClass: ep___admin_federation_removeAllFollowing.default };
-const $admin_federation_updateInstance: Provider = { provide: 'ep:admin/federation/update-instance', useClass: ep___admin_federation_updateInstance.default };
-const $admin_getIndexStats: Provider = { provide: 'ep:admin/get-index-stats', useClass: ep___admin_getIndexStats.default };
-const $admin_getTableStats: Provider = { provide: 'ep:admin/get-table-stats', useClass: ep___admin_getTableStats.default };
-const $admin_getUserIps: Provider = { provide: 'ep:admin/get-user-ips', useClass: ep___admin_getUserIps.default };
-const $admin_invite_create: Provider = { provide: 'ep:admin/invite/create', useClass: ep___admin_invite_create.default };
-const $admin_invite_list: Provider = { provide: 'ep:admin/invite/list', useClass: ep___admin_invite_list.default };
-const $admin_promo_create: Provider = { provide: 'ep:admin/promo/create', useClass: ep___admin_promo_create.default };
-const $admin_queue_clear: Provider = { provide: 'ep:admin/queue/clear', useClass: ep___admin_queue_clear.default };
-const $admin_queue_deliverDelayed: Provider = { provide: 'ep:admin/queue/deliver-delayed', useClass: ep___admin_queue_deliverDelayed.default };
-const $admin_queue_inboxDelayed: Provider = { provide: 'ep:admin/queue/inbox-delayed', useClass: ep___admin_queue_inboxDelayed.default };
-const $admin_queue_promote: Provider = { provide: 'ep:admin/queue/promote', useClass: ep___admin_queue_promote.default };
-const $admin_queue_stats: Provider = { provide: 'ep:admin/queue/stats', useClass: ep___admin_queue_stats.default };
-const $admin_relays_add: Provider = { provide: 'ep:admin/relays/add', useClass: ep___admin_relays_add.default };
-const $admin_relays_list: Provider = { provide: 'ep:admin/relays/list', useClass: ep___admin_relays_list.default };
-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 };
-const $admin_showUser: Provider = { provide: 'ep:admin/show-user', useClass: ep___admin_showUser.default };
-const $admin_showUsers: Provider = { provide: 'ep:admin/show-users', useClass: ep___admin_showUsers.default };
-const $admin_suspendUser: Provider = { provide: 'ep:admin/suspend-user', useClass: ep___admin_suspendUser.default };
-const $admin_unsuspendUser: Provider = { provide: 'ep:admin/unsuspend-user', useClass: ep___admin_unsuspendUser.default };
-const $admin_updateMeta: Provider = { provide: 'ep:admin/update-meta', useClass: ep___admin_updateMeta.default };
-const $admin_deleteAccount: Provider = { provide: 'ep:admin/delete-account', useClass: ep___admin_deleteAccount.default };
-const $admin_updateUserNote: Provider = { provide: 'ep:admin/update-user-note', useClass: ep___admin_updateUserNote.default };
-const $admin_roles_create: Provider = { provide: 'ep:admin/roles/create', useClass: ep___admin_roles_create.default };
-const $admin_roles_delete: Provider = { provide: 'ep:admin/roles/delete', useClass: ep___admin_roles_delete.default };
-const $admin_roles_list: Provider = { provide: 'ep:admin/roles/list', useClass: ep___admin_roles_list.default };
-const $admin_roles_show: Provider = { provide: 'ep:admin/roles/show', useClass: ep___admin_roles_show.default };
-const $admin_roles_update: Provider = { provide: 'ep:admin/roles/update', useClass: ep___admin_roles_update.default };
-const $admin_roles_assign: Provider = { provide: 'ep:admin/roles/assign', useClass: ep___admin_roles_assign.default };
-const $admin_roles_unassign: Provider = { provide: 'ep:admin/roles/unassign', useClass: ep___admin_roles_unassign.default };
-const $admin_roles_updateDefaultPolicies: Provider = { provide: 'ep:admin/roles/update-default-policies', useClass: ep___admin_roles_updateDefaultPolicies.default };
-const $admin_roles_users: Provider = { provide: 'ep:admin/roles/users', useClass: ep___admin_roles_users.default };
-const $admin_systemWebhook_create: Provider = { provide: 'ep:admin/system-webhook/create', useClass: ep___admin_systemWebhook_create.default };
-const $admin_systemWebhook_delete: Provider = { provide: 'ep:admin/system-webhook/delete', useClass: ep___admin_systemWebhook_delete.default };
-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 };
-const $antennas_delete: Provider = { provide: 'ep:antennas/delete', useClass: ep___antennas_delete.default };
-const $antennas_list: Provider = { provide: 'ep:antennas/list', useClass: ep___antennas_list.default };
-const $antennas_notes: Provider = { provide: 'ep:antennas/notes', useClass: ep___antennas_notes.default };
-const $antennas_show: Provider = { provide: 'ep:antennas/show', useClass: ep___antennas_show.default };
-const $antennas_update: Provider = { provide: 'ep:antennas/update', useClass: ep___antennas_update.default };
-const $ap_get: Provider = { provide: 'ep:ap/get', useClass: ep___ap_get.default };
-const $ap_show: Provider = { provide: 'ep:ap/show', useClass: ep___ap_show.default };
-const $app_create: Provider = { provide: 'ep:app/create', useClass: ep___app_create.default };
-const $app_show: Provider = { provide: 'ep:app/show', useClass: ep___app_show.default };
-const $auth_accept: Provider = { provide: 'ep:auth/accept', useClass: ep___auth_accept.default };
-const $auth_session_generate: Provider = { provide: 'ep:auth/session/generate', useClass: ep___auth_session_generate.default };
-const $auth_session_show: Provider = { provide: 'ep:auth/session/show', useClass: ep___auth_session_show.default };
-const $auth_session_userkey: Provider = { provide: 'ep:auth/session/userkey', useClass: ep___auth_session_userkey.default };
-const $blocking_create: Provider = { provide: 'ep:blocking/create', useClass: ep___blocking_create.default };
-const $blocking_delete: Provider = { provide: 'ep:blocking/delete', useClass: ep___blocking_delete.default };
-const $blocking_list: Provider = { provide: 'ep:blocking/list', useClass: ep___blocking_list.default };
-const $channels_create: Provider = { provide: 'ep:channels/create', useClass: ep___channels_create.default };
-const $channels_featured: Provider = { provide: 'ep:channels/featured', useClass: ep___channels_featured.default };
-const $channels_follow: Provider = { provide: 'ep:channels/follow', useClass: ep___channels_follow.default };
-const $channels_followed: Provider = { provide: 'ep:channels/followed', useClass: ep___channels_followed.default };
-const $channels_owned: Provider = { provide: 'ep:channels/owned', useClass: ep___channels_owned.default };
-const $channels_show: Provider = { provide: 'ep:channels/show', useClass: ep___channels_show.default };
-const $channels_timeline: Provider = { provide: 'ep:channels/timeline', useClass: ep___channels_timeline.default };
-const $channels_unfollow: Provider = { provide: 'ep:channels/unfollow', useClass: ep___channels_unfollow.default };
-const $channels_update: Provider = { provide: 'ep:channels/update', useClass: ep___channels_update.default };
-const $channels_favorite: Provider = { provide: 'ep:channels/favorite', useClass: ep___channels_favorite.default };
-const $channels_unfavorite: Provider = { provide: 'ep:channels/unfavorite', useClass: ep___channels_unfavorite.default };
-const $channels_myFavorites: Provider = { provide: 'ep:channels/my-favorites', useClass: ep___channels_myFavorites.default };
-const $channels_search: Provider = { provide: 'ep:channels/search', useClass: ep___channels_search.default };
-const $charts_activeUsers: Provider = { provide: 'ep:charts/active-users', useClass: ep___charts_activeUsers.default };
-const $charts_apRequest: Provider = { provide: 'ep:charts/ap-request', useClass: ep___charts_apRequest.default };
-const $charts_drive: Provider = { provide: 'ep:charts/drive', useClass: ep___charts_drive.default };
-const $charts_federation: Provider = { provide: 'ep:charts/federation', useClass: ep___charts_federation.default };
-const $charts_instance: Provider = { provide: 'ep:charts/instance', useClass: ep___charts_instance.default };
-const $charts_notes: Provider = { provide: 'ep:charts/notes', useClass: ep___charts_notes.default };
-const $charts_user_drive: Provider = { provide: 'ep:charts/user/drive', useClass: ep___charts_user_drive.default };
-const $charts_user_following: Provider = { provide: 'ep:charts/user/following', useClass: ep___charts_user_following.default };
-const $charts_user_notes: Provider = { provide: 'ep:charts/user/notes', useClass: ep___charts_user_notes.default };
-const $charts_user_pv: Provider = { provide: 'ep:charts/user/pv', useClass: ep___charts_user_pv.default };
-const $charts_user_reactions: Provider = { provide: 'ep:charts/user/reactions', useClass: ep___charts_user_reactions.default };
-const $charts_users: Provider = { provide: 'ep:charts/users', useClass: ep___charts_users.default };
-const $clips_addNote: Provider = { provide: 'ep:clips/add-note', useClass: ep___clips_addNote.default };
-const $clips_removeNote: Provider = { provide: 'ep:clips/remove-note', useClass: ep___clips_removeNote.default };
-const $clips_create: Provider = { provide: 'ep:clips/create', useClass: ep___clips_create.default };
-const $clips_delete: Provider = { provide: 'ep:clips/delete', useClass: ep___clips_delete.default };
-const $clips_list: Provider = { provide: 'ep:clips/list', useClass: ep___clips_list.default };
-const $clips_notes: Provider = { provide: 'ep:clips/notes', useClass: ep___clips_notes.default };
-const $clips_show: Provider = { provide: 'ep:clips/show', useClass: ep___clips_show.default };
-const $clips_update: Provider = { provide: 'ep:clips/update', useClass: ep___clips_update.default };
-const $clips_favorite: Provider = { provide: 'ep:clips/favorite', useClass: ep___clips_favorite.default };
-const $clips_unfavorite: Provider = { provide: 'ep:clips/unfavorite', useClass: ep___clips_unfavorite.default };
-const $clips_myFavorites: Provider = { provide: 'ep:clips/my-favorites', useClass: ep___clips_myFavorites.default };
-const $drive: Provider = { provide: 'ep:drive', useClass: ep___drive.default };
-const $drive_files: Provider = { provide: 'ep:drive/files', useClass: ep___drive_files.default };
-const $drive_files_attachedNotes: Provider = { provide: 'ep:drive/files/attached-notes', useClass: ep___drive_files_attachedNotes.default };
-const $drive_files_checkExistence: Provider = { provide: 'ep:drive/files/check-existence', useClass: ep___drive_files_checkExistence.default };
-const $drive_files_create: Provider = { provide: 'ep:drive/files/create', useClass: ep___drive_files_create.default };
-const $drive_files_delete: Provider = { provide: 'ep:drive/files/delete', useClass: ep___drive_files_delete.default };
-const $drive_files_findByHash: Provider = { provide: 'ep:drive/files/find-by-hash', useClass: ep___drive_files_findByHash.default };
-const $drive_files_find: Provider = { provide: 'ep:drive/files/find', useClass: ep___drive_files_find.default };
-const $drive_files_show: Provider = { provide: 'ep:drive/files/show', useClass: ep___drive_files_show.default };
-const $drive_files_update: Provider = { provide: 'ep:drive/files/update', useClass: ep___drive_files_update.default };
-const $drive_files_uploadFromUrl: Provider = { provide: 'ep:drive/files/upload-from-url', useClass: ep___drive_files_uploadFromUrl.default };
-const $drive_folders: Provider = { provide: 'ep:drive/folders', useClass: ep___drive_folders.default };
-const $drive_folders_create: Provider = { provide: 'ep:drive/folders/create', useClass: ep___drive_folders_create.default };
-const $drive_folders_delete: Provider = { provide: 'ep:drive/folders/delete', useClass: ep___drive_folders_delete.default };
-const $drive_folders_find: Provider = { provide: 'ep:drive/folders/find', useClass: ep___drive_folders_find.default };
-const $drive_folders_show: Provider = { provide: 'ep:drive/folders/show', useClass: ep___drive_folders_show.default };
-const $drive_folders_update: Provider = { provide: 'ep:drive/folders/update', useClass: ep___drive_folders_update.default };
-const $drive_stream: Provider = { provide: 'ep:drive/stream', useClass: ep___drive_stream.default };
-const $emailAddress_available: Provider = { provide: 'ep:email-address/available', useClass: ep___emailAddress_available.default };
-const $endpoint: Provider = { provide: 'ep:endpoint', useClass: ep___endpoint.default };
-const $endpoints: Provider = { provide: 'ep:endpoints', useClass: ep___endpoints.default };
-const $exportCustomEmojis: Provider = { provide: 'ep:export-custom-emojis', useClass: ep___exportCustomEmojis.default };
-const $federation_followers: Provider = { provide: 'ep:federation/followers', useClass: ep___federation_followers.default };
-const $federation_following: Provider = { provide: 'ep:federation/following', useClass: ep___federation_following.default };
-const $federation_instances: Provider = { provide: 'ep:federation/instances', useClass: ep___federation_instances.default };
-const $federation_showInstance: Provider = { provide: 'ep:federation/show-instance', useClass: ep___federation_showInstance.default };
-const $federation_updateRemoteUser: Provider = { provide: 'ep:federation/update-remote-user', useClass: ep___federation_updateRemoteUser.default };
-const $federation_users: Provider = { provide: 'ep:federation/users', useClass: ep___federation_users.default };
-const $federation_stats: Provider = { provide: 'ep:federation/stats', useClass: ep___federation_stats.default };
-const $following_create: Provider = { provide: 'ep:following/create', useClass: ep___following_create.default };
-const $following_delete: Provider = { provide: 'ep:following/delete', useClass: ep___following_delete.default };
-const $following_update: Provider = { provide: 'ep:following/update', useClass: ep___following_update.default };
-const $following_update_all: Provider = { provide: 'ep:following/update-all', useClass: ep___following_update_all.default };
-const $following_invalidate: Provider = { provide: 'ep:following/invalidate', useClass: ep___following_invalidate.default };
-const $following_requests_accept: Provider = { provide: 'ep:following/requests/accept', useClass: ep___following_requests_accept.default };
-const $following_requests_cancel: Provider = { provide: 'ep:following/requests/cancel', useClass: ep___following_requests_cancel.default };
-const $following_requests_list: Provider = { provide: 'ep:following/requests/list', useClass: ep___following_requests_list.default };
-const $following_requests_sent: Provider = { provide: 'ep:following/requests/sent', useClass: ep___following_requests_sent.default };
-const $following_requests_reject: Provider = { provide: 'ep:following/requests/reject', useClass: ep___following_requests_reject.default };
-const $gallery_featured: Provider = { provide: 'ep:gallery/featured', useClass: ep___gallery_featured.default };
-const $gallery_popular: Provider = { provide: 'ep:gallery/popular', useClass: ep___gallery_popular.default };
-const $gallery_posts: Provider = { provide: 'ep:gallery/posts', useClass: ep___gallery_posts.default };
-const $gallery_posts_create: Provider = { provide: 'ep:gallery/posts/create', useClass: ep___gallery_posts_create.default };
-const $gallery_posts_delete: Provider = { provide: 'ep:gallery/posts/delete', useClass: ep___gallery_posts_delete.default };
-const $gallery_posts_like: Provider = { provide: 'ep:gallery/posts/like', useClass: ep___gallery_posts_like.default };
-const $gallery_posts_show: Provider = { provide: 'ep:gallery/posts/show', useClass: ep___gallery_posts_show.default };
-const $gallery_posts_unlike: Provider = { provide: 'ep:gallery/posts/unlike', useClass: ep___gallery_posts_unlike.default };
-const $gallery_posts_update: Provider = { provide: 'ep:gallery/posts/update', useClass: ep___gallery_posts_update.default };
-const $getOnlineUsersCount: Provider = { provide: 'ep:get-online-users-count', useClass: ep___getOnlineUsersCount.default };
-const $getAvatarDecorations: Provider = { provide: 'ep:get-avatar-decorations', useClass: ep___getAvatarDecorations.default };
-const $hashtags_list: Provider = { provide: 'ep:hashtags/list', useClass: ep___hashtags_list.default };
-const $hashtags_search: Provider = { provide: 'ep:hashtags/search', useClass: ep___hashtags_search.default };
-const $hashtags_show: Provider = { provide: 'ep:hashtags/show', useClass: ep___hashtags_show.default };
-const $hashtags_trend: Provider = { provide: 'ep:hashtags/trend', useClass: ep___hashtags_trend.default };
-const $hashtags_users: Provider = { provide: 'ep:hashtags/users', useClass: ep___hashtags_users.default };
-const $i: Provider = { provide: 'ep:i', useClass: ep___i.default };
-const $i_2fa_done: Provider = { provide: 'ep:i/2fa/done', useClass: ep___i_2fa_done.default };
-const $i_2fa_keyDone: Provider = { provide: 'ep:i/2fa/key-done', useClass: ep___i_2fa_keyDone.default };
-const $i_2fa_passwordLess: Provider = { provide: 'ep:i/2fa/password-less', useClass: ep___i_2fa_passwordLess.default };
-const $i_2fa_registerKey: Provider = { provide: 'ep:i/2fa/register-key', useClass: ep___i_2fa_registerKey.default };
-const $i_2fa_register: Provider = { provide: 'ep:i/2fa/register', useClass: ep___i_2fa_register.default };
-const $i_2fa_updateKey: Provider = { provide: 'ep:i/2fa/update-key', useClass: ep___i_2fa_updateKey.default };
-const $i_2fa_removeKey: Provider = { provide: 'ep:i/2fa/remove-key', useClass: ep___i_2fa_removeKey.default };
-const $i_2fa_unregister: Provider = { provide: 'ep:i/2fa/unregister', useClass: ep___i_2fa_unregister.default };
-const $i_apps: Provider = { provide: 'ep:i/apps', useClass: ep___i_apps.default };
-const $i_authorizedApps: Provider = { provide: 'ep:i/authorized-apps', useClass: ep___i_authorizedApps.default };
-const $i_claimAchievement: Provider = { provide: 'ep:i/claim-achievement', useClass: ep___i_claimAchievement.default };
-const $i_changePassword: Provider = { provide: 'ep:i/change-password', useClass: ep___i_changePassword.default };
-const $i_deleteAccount: Provider = { provide: 'ep:i/delete-account', useClass: ep___i_deleteAccount.default };
-const $i_exportBlocking: Provider = { provide: 'ep:i/export-blocking', useClass: ep___i_exportBlocking.default };
-const $i_exportFollowing: Provider = { provide: 'ep:i/export-following', useClass: ep___i_exportFollowing.default };
-const $i_exportMute: Provider = { provide: 'ep:i/export-mute', useClass: ep___i_exportMute.default };
-const $i_exportNotes: Provider = { provide: 'ep:i/export-notes', useClass: ep___i_exportNotes.default };
-const $i_exportClips: Provider = { provide: 'ep:i/export-clips', useClass: ep___i_exportClips.default };
-const $i_exportFavorites: Provider = { provide: 'ep:i/export-favorites', useClass: ep___i_exportFavorites.default };
-const $i_exportUserLists: Provider = { provide: 'ep:i/export-user-lists', useClass: ep___i_exportUserLists.default };
-const $i_exportAntennas: Provider = { provide: 'ep:i/export-antennas', useClass: ep___i_exportAntennas.default };
-const $i_favorites: Provider = { provide: 'ep:i/favorites', useClass: ep___i_favorites.default };
-const $i_gallery_likes: Provider = { provide: 'ep:i/gallery/likes', useClass: ep___i_gallery_likes.default };
-const $i_gallery_posts: Provider = { provide: 'ep:i/gallery/posts', useClass: ep___i_gallery_posts.default };
-const $i_importBlocking: Provider = { provide: 'ep:i/import-blocking', useClass: ep___i_importBlocking.default };
-const $i_importFollowing: Provider = { provide: 'ep:i/import-following', useClass: ep___i_importFollowing.default };
-const $i_importMuting: Provider = { provide: 'ep:i/import-muting', useClass: ep___i_importMuting.default };
-const $i_importUserLists: Provider = { provide: 'ep:i/import-user-lists', useClass: ep___i_importUserLists.default };
-const $i_importAntennas: Provider = { provide: 'ep:i/import-antennas', useClass: ep___i_importAntennas.default };
-const $i_notifications: Provider = { provide: 'ep:i/notifications', useClass: ep___i_notifications.default };
-const $i_notificationsGrouped: Provider = { provide: 'ep:i/notifications-grouped', useClass: ep___i_notificationsGrouped.default };
-const $i_pageLikes: Provider = { provide: 'ep:i/page-likes', useClass: ep___i_pageLikes.default };
-const $i_pages: Provider = { provide: 'ep:i/pages', useClass: ep___i_pages.default };
-const $i_pin: Provider = { provide: 'ep:i/pin', useClass: ep___i_pin.default };
-const $i_readAllUnreadNotes: Provider = { provide: 'ep:i/read-all-unread-notes', useClass: ep___i_readAllUnreadNotes.default };
-const $i_readAnnouncement: Provider = { provide: 'ep:i/read-announcement', useClass: ep___i_readAnnouncement.default };
-const $i_regenerateToken: Provider = { provide: 'ep:i/regenerate-token', useClass: ep___i_regenerateToken.default };
-const $i_registry_getAll: Provider = { provide: 'ep:i/registry/get-all', useClass: ep___i_registry_getAll.default };
-const $i_registry_getDetail: Provider = { provide: 'ep:i/registry/get-detail', useClass: ep___i_registry_getDetail.default };
-const $i_registry_get: Provider = { provide: 'ep:i/registry/get', useClass: ep___i_registry_get.default };
-const $i_registry_keysWithType: Provider = { provide: 'ep:i/registry/keys-with-type', useClass: ep___i_registry_keysWithType.default };
-const $i_registry_keys: Provider = { provide: 'ep:i/registry/keys', useClass: ep___i_registry_keys.default };
-const $i_registry_remove: Provider = { provide: 'ep:i/registry/remove', useClass: ep___i_registry_remove.default };
-const $i_registry_scopesWithDomain: Provider = { provide: 'ep:i/registry/scopes-with-domain', useClass: ep___i_registry_scopesWithDomain.default };
-const $i_registry_set: Provider = { provide: 'ep:i/registry/set', useClass: ep___i_registry_set.default };
-const $i_revokeToken: Provider = { provide: 'ep:i/revoke-token', useClass: ep___i_revokeToken.default };
-const $i_signinHistory: Provider = { provide: 'ep:i/signin-history', useClass: ep___i_signinHistory.default };
-const $i_unpin: Provider = { provide: 'ep:i/unpin', useClass: ep___i_unpin.default };
-const $i_updateEmail: Provider = { provide: 'ep:i/update-email', useClass: ep___i_updateEmail.default };
-const $i_update: Provider = { provide: 'ep:i/update', useClass: ep___i_update.default };
-const $i_move: Provider = { provide: 'ep:i/move', useClass: ep___i_move.default };
-const $i_webhooks_create: Provider = { provide: 'ep:i/webhooks/create', useClass: ep___i_webhooks_create.default };
-const $i_webhooks_list: Provider = { provide: 'ep:i/webhooks/list', useClass: ep___i_webhooks_list.default };
-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 };
-const $invite_limit: Provider = { provide: 'ep:invite/limit', useClass: ep___invite_limit.default };
-const $meta: Provider = { provide: 'ep:meta', useClass: ep___meta.default };
-const $emojis: Provider = { provide: 'ep:emojis', useClass: ep___emojis.default };
-const $emoji: Provider = { provide: 'ep:emoji', useClass: ep___emoji.default };
-const $miauth_genToken: Provider = { provide: 'ep:miauth/gen-token', useClass: ep___miauth_genToken.default };
-const $mute_create: Provider = { provide: 'ep:mute/create', useClass: ep___mute_create.default };
-const $mute_delete: Provider = { provide: 'ep:mute/delete', useClass: ep___mute_delete.default };
-const $mute_list: Provider = { provide: 'ep:mute/list', useClass: ep___mute_list.default };
-const $renoteMute_create: Provider = { provide: 'ep:renote-mute/create', useClass: ep___renoteMute_create.default };
-const $renoteMute_delete: Provider = { provide: 'ep:renote-mute/delete', useClass: ep___renoteMute_delete.default };
-const $renoteMute_list: Provider = { provide: 'ep:renote-mute/list', useClass: ep___renoteMute_list.default };
-const $my_apps: Provider = { provide: 'ep:my/apps', useClass: ep___my_apps.default };
-const $notes: Provider = { provide: 'ep:notes', useClass: ep___notes.default };
-const $notes_children: Provider = { provide: 'ep:notes/children', useClass: ep___notes_children.default };
-const $notes_clips: Provider = { provide: 'ep:notes/clips', useClass: ep___notes_clips.default };
-const $notes_conversation: Provider = { provide: 'ep:notes/conversation', useClass: ep___notes_conversation.default };
-const $notes_create: Provider = { provide: 'ep:notes/create', useClass: ep___notes_create.default };
-const $notes_delete: Provider = { provide: 'ep:notes/delete', useClass: ep___notes_delete.default };
-const $notes_favorites_create: Provider = { provide: 'ep:notes/favorites/create', useClass: ep___notes_favorites_create.default };
-const $notes_favorites_delete: Provider = { provide: 'ep:notes/favorites/delete', useClass: ep___notes_favorites_delete.default };
-const $notes_featured: Provider = { provide: 'ep:notes/featured', useClass: ep___notes_featured.default };
-const $notes_globalTimeline: Provider = { provide: 'ep:notes/global-timeline', useClass: ep___notes_globalTimeline.default };
-const $notes_hybridTimeline: Provider = { provide: 'ep:notes/hybrid-timeline', useClass: ep___notes_hybridTimeline.default };
-const $notes_localTimeline: Provider = { provide: 'ep:notes/local-timeline', useClass: ep___notes_localTimeline.default };
-const $notes_mentions: Provider = { provide: 'ep:notes/mentions', useClass: ep___notes_mentions.default };
-const $notes_polls_recommendation: Provider = { provide: 'ep:notes/polls/recommendation', useClass: ep___notes_polls_recommendation.default };
-const $notes_polls_vote: Provider = { provide: 'ep:notes/polls/vote', useClass: ep___notes_polls_vote.default };
-const $notes_reactions: Provider = { provide: 'ep:notes/reactions', useClass: ep___notes_reactions.default };
-const $notes_reactions_create: Provider = { provide: 'ep:notes/reactions/create', useClass: ep___notes_reactions_create.default };
-const $notes_reactions_delete: Provider = { provide: 'ep:notes/reactions/delete', useClass: ep___notes_reactions_delete.default };
-const $notes_renotes: Provider = { provide: 'ep:notes/renotes', useClass: ep___notes_renotes.default };
-const $notes_replies: Provider = { provide: 'ep:notes/replies', useClass: ep___notes_replies.default };
-const $notes_searchByTag: Provider = { provide: 'ep:notes/search-by-tag', useClass: ep___notes_searchByTag.default };
-const $notes_search: Provider = { provide: 'ep:notes/search', useClass: ep___notes_search.default };
-const $notes_show: Provider = { provide: 'ep:notes/show', useClass: ep___notes_show.default };
-const $notes_state: Provider = { provide: 'ep:notes/state', useClass: ep___notes_state.default };
-const $notes_threadMuting_create: Provider = { provide: 'ep:notes/thread-muting/create', useClass: ep___notes_threadMuting_create.default };
-const $notes_threadMuting_delete: Provider = { provide: 'ep:notes/thread-muting/delete', useClass: ep___notes_threadMuting_delete.default };
-const $notes_timeline: Provider = { provide: 'ep:notes/timeline', useClass: ep___notes_timeline.default };
-const $notes_translate: Provider = { provide: 'ep:notes/translate', useClass: ep___notes_translate.default };
-const $notes_unrenote: Provider = { provide: 'ep:notes/unrenote', useClass: ep___notes_unrenote.default };
-const $notes_userListTimeline: Provider = { provide: 'ep:notes/user-list-timeline', useClass: ep___notes_userListTimeline.default };
-const $notifications_create: Provider = { provide: 'ep:notifications/create', useClass: ep___notifications_create.default };
-const $notifications_flush: Provider = { provide: 'ep:notifications/flush', useClass: ep___notifications_flush.default };
-const $notifications_markAllAsRead: Provider = { provide: 'ep:notifications/mark-all-as-read', useClass: ep___notifications_markAllAsRead.default };
-const $notifications_testNotification: Provider = { provide: 'ep:notifications/test-notification', useClass: ep___notifications_testNotification.default };
-const $pagePush: Provider = { provide: 'ep:page-push', useClass: ep___pagePush.default };
-const $pages_create: Provider = { provide: 'ep:pages/create', useClass: ep___pages_create.default };
-const $pages_delete: Provider = { provide: 'ep:pages/delete', useClass: ep___pages_delete.default };
-const $pages_featured: Provider = { provide: 'ep:pages/featured', useClass: ep___pages_featured.default };
-const $pages_like: Provider = { provide: 'ep:pages/like', useClass: ep___pages_like.default };
-const $pages_show: Provider = { provide: 'ep:pages/show', useClass: ep___pages_show.default };
-const $pages_unlike: Provider = { provide: 'ep:pages/unlike', useClass: ep___pages_unlike.default };
-const $pages_update: Provider = { provide: 'ep:pages/update', useClass: ep___pages_update.default };
-const $flash_create: Provider = { provide: 'ep:flash/create', useClass: ep___flash_create.default };
-const $flash_delete: Provider = { provide: 'ep:flash/delete', useClass: ep___flash_delete.default };
-const $flash_featured: Provider = { provide: 'ep:flash/featured', useClass: ep___flash_featured.default };
-const $flash_like: Provider = { provide: 'ep:flash/like', useClass: ep___flash_like.default };
-const $flash_show: Provider = { provide: 'ep:flash/show', useClass: ep___flash_show.default };
-const $flash_unlike: Provider = { provide: 'ep:flash/unlike', useClass: ep___flash_unlike.default };
-const $flash_update: Provider = { provide: 'ep:flash/update', useClass: ep___flash_update.default };
-const $flash_my: Provider = { provide: 'ep:flash/my', useClass: ep___flash_my.default };
-const $flash_myLikes: Provider = { provide: 'ep:flash/my-likes', useClass: ep___flash_myLikes.default };
-const $ping: Provider = { provide: 'ep:ping', useClass: ep___ping.default };
-const $pinnedUsers: Provider = { provide: 'ep:pinned-users', useClass: ep___pinnedUsers.default };
-const $promo_read: Provider = { provide: 'ep:promo/read', useClass: ep___promo_read.default };
-const $roles_list: Provider = { provide: 'ep:roles/list', useClass: ep___roles_list.default };
-const $roles_show: Provider = { provide: 'ep:roles/show', useClass: ep___roles_show.default };
-const $roles_users: Provider = { provide: 'ep:roles/users', useClass: ep___roles_users.default };
-const $roles_notes: Provider = { provide: 'ep:roles/notes', useClass: ep___roles_notes.default };
-const $requestResetPassword: Provider = { provide: 'ep:request-reset-password', useClass: ep___requestResetPassword.default };
-const $resetDb: Provider = { provide: 'ep:reset-db', useClass: ep___resetDb.default };
-const $resetPassword: Provider = { provide: 'ep:reset-password', useClass: ep___resetPassword.default };
-const $serverInfo: Provider = { provide: 'ep:server-info', useClass: ep___serverInfo.default };
-const $stats: Provider = { provide: 'ep:stats', useClass: ep___stats.default };
-const $sw_show_registration: Provider = { provide: 'ep:sw/show-registration', useClass: ep___sw_show_registration.default };
-const $sw_update_registration: Provider = { provide: 'ep:sw/update-registration', useClass: ep___sw_update_registration.default };
-const $sw_register: Provider = { provide: 'ep:sw/register', useClass: ep___sw_register.default };
-const $sw_unregister: Provider = { provide: 'ep:sw/unregister', useClass: ep___sw_unregister.default };
-const $test: Provider = { provide: 'ep:test', useClass: ep___test.default };
-const $username_available: Provider = { provide: 'ep:username/available', useClass: ep___username_available.default };
-const $users: Provider = { provide: 'ep:users', useClass: ep___users.default };
-const $users_clips: Provider = { provide: 'ep:users/clips', useClass: ep___users_clips.default };
-const $users_followers: Provider = { provide: 'ep:users/followers', useClass: ep___users_followers.default };
-const $users_following: Provider = { provide: 'ep:users/following', useClass: ep___users_following.default };
-const $users_gallery_posts: Provider = { provide: 'ep:users/gallery/posts', useClass: ep___users_gallery_posts.default };
-const $users_getFrequentlyRepliedUsers: Provider = { provide: 'ep:users/get-frequently-replied-users', useClass: ep___users_getFrequentlyRepliedUsers.default };
-const $users_featuredNotes: Provider = { provide: 'ep:users/featured-notes', useClass: ep___users_featuredNotes.default };
-const $users_lists_create: Provider = { provide: 'ep:users/lists/create', useClass: ep___users_lists_create.default };
-const $users_lists_delete: Provider = { provide: 'ep:users/lists/delete', useClass: ep___users_lists_delete.default };
-const $users_lists_list: Provider = { provide: 'ep:users/lists/list', useClass: ep___users_lists_list.default };
-const $users_lists_pull: Provider = { provide: 'ep:users/lists/pull', useClass: ep___users_lists_pull.default };
-const $users_lists_push: Provider = { provide: 'ep:users/lists/push', useClass: ep___users_lists_push.default };
-const $users_lists_show: Provider = { provide: 'ep:users/lists/show', useClass: ep___users_lists_show.default };
-const $users_lists_update: Provider = { provide: 'ep:users/lists/update', useClass: ep___users_lists_update.default };
-const $users_lists_favorite: Provider = { provide: 'ep:users/lists/favorite', useClass: ep___users_lists_favorite.default };
-const $users_lists_unfavorite: Provider = { provide: 'ep:users/lists/unfavorite', useClass: ep___users_lists_unfavorite.default };
-const $users_lists_createFromPublic: Provider = { provide: 'ep:users/lists/create-from-public', useClass: ep___users_lists_createFromPublic.default };
-const $users_lists_updateMembership: Provider = { provide: 'ep:users/lists/update-membership', useClass: ep___users_lists_updateMembership.default };
-const $users_lists_getMemberships: Provider = { provide: 'ep:users/lists/get-memberships', useClass: ep___users_lists_getMemberships.default };
-const $users_notes: Provider = { provide: 'ep:users/notes', useClass: ep___users_notes.default };
-const $users_pages: Provider = { provide: 'ep:users/pages', useClass: ep___users_pages.default };
-const $users_flashs: Provider = { provide: 'ep:users/flashs', useClass: ep___users_flashs.default };
-const $users_reactions: Provider = { provide: 'ep:users/reactions', useClass: ep___users_reactions.default };
-const $users_recommendation: Provider = { provide: 'ep:users/recommendation', useClass: ep___users_recommendation.default };
-const $users_relation: Provider = { provide: 'ep:users/relation', useClass: ep___users_relation.default };
-const $users_reportAbuse: Provider = { provide: 'ep:users/report-abuse', useClass: ep___users_reportAbuse.default };
-const $users_searchByUsernameAndHost: Provider = { provide: 'ep:users/search-by-username-and-host', useClass: ep___users_searchByUsernameAndHost.default };
-const $users_search: Provider = { provide: 'ep:users/search', useClass: ep___users_search.default };
-const $users_show: Provider = { provide: 'ep:users/show', useClass: ep___users_show.default };
-const $users_achievements: Provider = { provide: 'ep:users/achievements', useClass: ep___users_achievements.default };
-const $users_updateMemo: Provider = { provide: 'ep:users/update-memo', useClass: ep___users_updateMemo.default };
-const $fetchRss: Provider = { provide: 'ep:fetch-rss', useClass: ep___fetchRss.default };
-const $fetchExternalResources: Provider = { provide: 'ep:fetch-external-resources', useClass: ep___fetchExternalResources.default };
-const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention.default };
-const $bubbleGame_register: Provider = { provide: 'ep:bubble-game/register', useClass: ep___bubbleGame_register.default };
-const $bubbleGame_ranking: Provider = { provide: 'ep:bubble-game/ranking', useClass: ep___bubbleGame_ranking.default };
-const $reversi_cancelMatch: Provider = { provide: 'ep:reversi/cancel-match', useClass: ep___reversi_cancelMatch.default };
-const $reversi_games: Provider = { provide: 'ep:reversi/games', useClass: ep___reversi_games.default };
-const $reversi_match: Provider = { provide: 'ep:reversi/match', useClass: ep___reversi_match.default };
-const $reversi_invitations: Provider = { provide: 'ep:reversi/invitations', useClass: ep___reversi_invitations.default };
-const $reversi_showGame: Provider = { provide: 'ep:reversi/show-game', useClass: ep___reversi_showGame.default };
-const $reversi_surrender: Provider = { provide: 'ep:reversi/surrender', useClass: ep___reversi_surrender.default };
-const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep___reversi_verify.default };
+const endpoints = Object.entries(endpointsObject);
+const endpointProviders = endpoints.map(([path, endpoint]): Provider => ({ provide: `ep:${path}`, useClass: endpoint.default }));
@Module({
imports: [
@@ -786,773 +21,10 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
providers: [
GetterService,
ApiLoggerService,
- $admin_meta,
- $admin_abuseUserReports,
- $admin_abuseReport_notificationRecipient_list,
- $admin_abuseReport_notificationRecipient_show,
- $admin_abuseReport_notificationRecipient_create,
- $admin_abuseReport_notificationRecipient_update,
- $admin_abuseReport_notificationRecipient_delete,
- $admin_accounts_create,
- $admin_accounts_delete,
- $admin_accounts_findByEmail,
- $admin_ad_create,
- $admin_ad_delete,
- $admin_ad_list,
- $admin_ad_update,
- $admin_announcements_create,
- $admin_announcements_delete,
- $admin_announcements_list,
- $admin_announcements_update,
- $admin_avatarDecorations_create,
- $admin_avatarDecorations_delete,
- $admin_avatarDecorations_list,
- $admin_avatarDecorations_update,
- $admin_deleteAllFilesOfAUser,
- $admin_unsetUserAvatar,
- $admin_unsetUserBanner,
- $admin_drive_cleanRemoteFiles,
- $admin_drive_cleanup,
- $admin_drive_files,
- $admin_drive_showFile,
- $admin_emoji_addAliasesBulk,
- $admin_emoji_add,
- $admin_emoji_copy,
- $admin_emoji_deleteBulk,
- $admin_emoji_delete,
- $admin_emoji_importZip,
- $admin_emoji_listRemote,
- $admin_emoji_list,
- $admin_emoji_removeAliasesBulk,
- $admin_emoji_setAliasesBulk,
- $admin_emoji_setCategoryBulk,
- $admin_emoji_setLicenseBulk,
- $admin_emoji_update,
- $admin_federation_deleteAllFiles,
- $admin_federation_refreshRemoteInstanceMetadata,
- $admin_federation_removeAllFollowing,
- $admin_federation_updateInstance,
- $admin_getIndexStats,
- $admin_getTableStats,
- $admin_getUserIps,
- $admin_invite_create,
- $admin_invite_list,
- $admin_promo_create,
- $admin_queue_clear,
- $admin_queue_deliverDelayed,
- $admin_queue_inboxDelayed,
- $admin_queue_promote,
- $admin_queue_stats,
- $admin_relays_add,
- $admin_relays_list,
- $admin_relays_remove,
- $admin_resetPassword,
- $admin_resolveAbuseUserReport,
- $admin_forwardAbuseUserReport,
- $admin_updateAbuseUserReport,
- $admin_sendEmail,
- $admin_serverInfo,
- $admin_showModerationLogs,
- $admin_showUser,
- $admin_showUsers,
- $admin_suspendUser,
- $admin_unsuspendUser,
- $admin_updateMeta,
- $admin_deleteAccount,
- $admin_updateUserNote,
- $admin_roles_create,
- $admin_roles_delete,
- $admin_roles_list,
- $admin_roles_show,
- $admin_roles_update,
- $admin_roles_assign,
- $admin_roles_unassign,
- $admin_roles_updateDefaultPolicies,
- $admin_roles_users,
- $admin_systemWebhook_create,
- $admin_systemWebhook_delete,
- $admin_systemWebhook_list,
- $admin_systemWebhook_show,
- $admin_systemWebhook_update,
- $admin_systemWebhook_test,
- $announcements,
- $announcements_show,
- $antennas_create,
- $antennas_delete,
- $antennas_list,
- $antennas_notes,
- $antennas_show,
- $antennas_update,
- $ap_get,
- $ap_show,
- $app_create,
- $app_show,
- $auth_accept,
- $auth_session_generate,
- $auth_session_show,
- $auth_session_userkey,
- $blocking_create,
- $blocking_delete,
- $blocking_list,
- $channels_create,
- $channels_featured,
- $channels_follow,
- $channels_followed,
- $channels_owned,
- $channels_show,
- $channels_timeline,
- $channels_unfollow,
- $channels_update,
- $channels_favorite,
- $channels_unfavorite,
- $channels_myFavorites,
- $channels_search,
- $charts_activeUsers,
- $charts_apRequest,
- $charts_drive,
- $charts_federation,
- $charts_instance,
- $charts_notes,
- $charts_user_drive,
- $charts_user_following,
- $charts_user_notes,
- $charts_user_pv,
- $charts_user_reactions,
- $charts_users,
- $clips_addNote,
- $clips_removeNote,
- $clips_create,
- $clips_delete,
- $clips_list,
- $clips_notes,
- $clips_show,
- $clips_update,
- $clips_favorite,
- $clips_unfavorite,
- $clips_myFavorites,
- $drive,
- $drive_files,
- $drive_files_attachedNotes,
- $drive_files_checkExistence,
- $drive_files_create,
- $drive_files_delete,
- $drive_files_findByHash,
- $drive_files_find,
- $drive_files_show,
- $drive_files_update,
- $drive_files_uploadFromUrl,
- $drive_folders,
- $drive_folders_create,
- $drive_folders_delete,
- $drive_folders_find,
- $drive_folders_show,
- $drive_folders_update,
- $drive_stream,
- $emailAddress_available,
- $endpoint,
- $endpoints,
- $exportCustomEmojis,
- $federation_followers,
- $federation_following,
- $federation_instances,
- $federation_showInstance,
- $federation_updateRemoteUser,
- $federation_users,
- $federation_stats,
- $following_create,
- $following_delete,
- $following_update,
- $following_update_all,
- $following_invalidate,
- $following_requests_accept,
- $following_requests_cancel,
- $following_requests_list,
- $following_requests_sent,
- $following_requests_reject,
- $gallery_featured,
- $gallery_popular,
- $gallery_posts,
- $gallery_posts_create,
- $gallery_posts_delete,
- $gallery_posts_like,
- $gallery_posts_show,
- $gallery_posts_unlike,
- $gallery_posts_update,
- $getOnlineUsersCount,
- $getAvatarDecorations,
- $hashtags_list,
- $hashtags_search,
- $hashtags_show,
- $hashtags_trend,
- $hashtags_users,
- $i,
- $i_2fa_done,
- $i_2fa_keyDone,
- $i_2fa_passwordLess,
- $i_2fa_registerKey,
- $i_2fa_register,
- $i_2fa_updateKey,
- $i_2fa_removeKey,
- $i_2fa_unregister,
- $i_apps,
- $i_authorizedApps,
- $i_claimAchievement,
- $i_changePassword,
- $i_deleteAccount,
- $i_exportBlocking,
- $i_exportFollowing,
- $i_exportMute,
- $i_exportNotes,
- $i_exportClips,
- $i_exportFavorites,
- $i_exportUserLists,
- $i_exportAntennas,
- $i_favorites,
- $i_gallery_likes,
- $i_gallery_posts,
- $i_importBlocking,
- $i_importFollowing,
- $i_importMuting,
- $i_importUserLists,
- $i_importAntennas,
- $i_notifications,
- $i_notificationsGrouped,
- $i_pageLikes,
- $i_pages,
- $i_pin,
- $i_readAllUnreadNotes,
- $i_readAnnouncement,
- $i_regenerateToken,
- $i_registry_getAll,
- $i_registry_getDetail,
- $i_registry_get,
- $i_registry_keysWithType,
- $i_registry_keys,
- $i_registry_remove,
- $i_registry_scopesWithDomain,
- $i_registry_set,
- $i_revokeToken,
- $i_signinHistory,
- $i_unpin,
- $i_updateEmail,
- $i_update,
- $i_move,
- $i_webhooks_create,
- $i_webhooks_list,
- $i_webhooks_show,
- $i_webhooks_update,
- $i_webhooks_delete,
- $i_webhooks_test,
- $invite_create,
- $invite_delete,
- $invite_list,
- $invite_limit,
- $meta,
- $emojis,
- $emoji,
- $miauth_genToken,
- $mute_create,
- $mute_delete,
- $mute_list,
- $renoteMute_create,
- $renoteMute_delete,
- $renoteMute_list,
- $my_apps,
- $notes,
- $notes_children,
- $notes_clips,
- $notes_conversation,
- $notes_create,
- $notes_delete,
- $notes_favorites_create,
- $notes_favorites_delete,
- $notes_featured,
- $notes_globalTimeline,
- $notes_hybridTimeline,
- $notes_localTimeline,
- $notes_mentions,
- $notes_polls_recommendation,
- $notes_polls_vote,
- $notes_reactions,
- $notes_reactions_create,
- $notes_reactions_delete,
- $notes_renotes,
- $notes_replies,
- $notes_searchByTag,
- $notes_search,
- $notes_show,
- $notes_state,
- $notes_threadMuting_create,
- $notes_threadMuting_delete,
- $notes_timeline,
- $notes_translate,
- $notes_unrenote,
- $notes_userListTimeline,
- $notifications_create,
- $notifications_flush,
- $notifications_markAllAsRead,
- $notifications_testNotification,
- $pagePush,
- $pages_create,
- $pages_delete,
- $pages_featured,
- $pages_like,
- $pages_show,
- $pages_unlike,
- $pages_update,
- $flash_create,
- $flash_delete,
- $flash_featured,
- $flash_like,
- $flash_show,
- $flash_unlike,
- $flash_update,
- $flash_my,
- $flash_myLikes,
- $ping,
- $pinnedUsers,
- $promo_read,
- $roles_list,
- $roles_show,
- $roles_users,
- $roles_notes,
- $requestResetPassword,
- $resetDb,
- $resetPassword,
- $serverInfo,
- $stats,
- $sw_show_registration,
- $sw_update_registration,
- $sw_register,
- $sw_unregister,
- $test,
- $username_available,
- $users,
- $users_clips,
- $users_followers,
- $users_following,
- $users_gallery_posts,
- $users_getFrequentlyRepliedUsers,
- $users_featuredNotes,
- $users_lists_create,
- $users_lists_delete,
- $users_lists_list,
- $users_lists_pull,
- $users_lists_push,
- $users_lists_show,
- $users_lists_update,
- $users_lists_favorite,
- $users_lists_unfavorite,
- $users_lists_createFromPublic,
- $users_lists_updateMembership,
- $users_lists_getMemberships,
- $users_notes,
- $users_pages,
- $users_flashs,
- $users_reactions,
- $users_recommendation,
- $users_relation,
- $users_reportAbuse,
- $users_searchByUsernameAndHost,
- $users_search,
- $users_show,
- $users_achievements,
- $users_updateMemo,
- $fetchRss,
- $fetchExternalResources,
- $retention,
- $bubbleGame_register,
- $bubbleGame_ranking,
- $reversi_cancelMatch,
- $reversi_games,
- $reversi_match,
- $reversi_invitations,
- $reversi_showGame,
- $reversi_surrender,
- $reversi_verify,
+ ...endpointProviders,
],
exports: [
- $admin_meta,
- $admin_abuseUserReports,
- $admin_abuseReport_notificationRecipient_list,
- $admin_abuseReport_notificationRecipient_show,
- $admin_abuseReport_notificationRecipient_create,
- $admin_abuseReport_notificationRecipient_update,
- $admin_abuseReport_notificationRecipient_delete,
- $admin_accounts_create,
- $admin_accounts_delete,
- $admin_accounts_findByEmail,
- $admin_ad_create,
- $admin_ad_delete,
- $admin_ad_list,
- $admin_ad_update,
- $admin_announcements_create,
- $admin_announcements_delete,
- $admin_announcements_list,
- $admin_announcements_update,
- $admin_avatarDecorations_create,
- $admin_avatarDecorations_delete,
- $admin_avatarDecorations_list,
- $admin_avatarDecorations_update,
- $admin_deleteAllFilesOfAUser,
- $admin_unsetUserAvatar,
- $admin_unsetUserBanner,
- $admin_drive_cleanRemoteFiles,
- $admin_drive_cleanup,
- $admin_drive_files,
- $admin_drive_showFile,
- $admin_emoji_addAliasesBulk,
- $admin_emoji_add,
- $admin_emoji_copy,
- $admin_emoji_deleteBulk,
- $admin_emoji_delete,
- $admin_emoji_importZip,
- $admin_emoji_listRemote,
- $admin_emoji_list,
- $admin_emoji_removeAliasesBulk,
- $admin_emoji_setAliasesBulk,
- $admin_emoji_setCategoryBulk,
- $admin_emoji_setLicenseBulk,
- $admin_emoji_update,
- $admin_federation_deleteAllFiles,
- $admin_federation_refreshRemoteInstanceMetadata,
- $admin_federation_removeAllFollowing,
- $admin_federation_updateInstance,
- $admin_getIndexStats,
- $admin_getTableStats,
- $admin_getUserIps,
- $admin_invite_create,
- $admin_invite_list,
- $admin_promo_create,
- $admin_queue_clear,
- $admin_queue_deliverDelayed,
- $admin_queue_inboxDelayed,
- $admin_queue_promote,
- $admin_queue_stats,
- $admin_relays_add,
- $admin_relays_list,
- $admin_relays_remove,
- $admin_resetPassword,
- $admin_resolveAbuseUserReport,
- $admin_forwardAbuseUserReport,
- $admin_updateAbuseUserReport,
- $admin_sendEmail,
- $admin_serverInfo,
- $admin_showModerationLogs,
- $admin_showUser,
- $admin_showUsers,
- $admin_suspendUser,
- $admin_unsuspendUser,
- $admin_updateMeta,
- $admin_deleteAccount,
- $admin_updateUserNote,
- $admin_roles_create,
- $admin_roles_delete,
- $admin_roles_list,
- $admin_roles_show,
- $admin_roles_update,
- $admin_roles_assign,
- $admin_roles_unassign,
- $admin_roles_updateDefaultPolicies,
- $admin_roles_users,
- $admin_systemWebhook_create,
- $admin_systemWebhook_delete,
- $admin_systemWebhook_list,
- $admin_systemWebhook_show,
- $admin_systemWebhook_update,
- $admin_systemWebhook_test,
- $announcements,
- $announcements_show,
- $antennas_create,
- $antennas_delete,
- $antennas_list,
- $antennas_notes,
- $antennas_show,
- $antennas_update,
- $ap_get,
- $ap_show,
- $app_create,
- $app_show,
- $auth_accept,
- $auth_session_generate,
- $auth_session_show,
- $auth_session_userkey,
- $blocking_create,
- $blocking_delete,
- $blocking_list,
- $channels_create,
- $channels_featured,
- $channels_follow,
- $channels_followed,
- $channels_owned,
- $channels_show,
- $channels_timeline,
- $channels_unfollow,
- $channels_update,
- $channels_favorite,
- $channels_unfavorite,
- $channels_myFavorites,
- $channels_search,
- $charts_activeUsers,
- $charts_apRequest,
- $charts_drive,
- $charts_federation,
- $charts_instance,
- $charts_notes,
- $charts_user_drive,
- $charts_user_following,
- $charts_user_notes,
- $charts_user_pv,
- $charts_user_reactions,
- $charts_users,
- $clips_addNote,
- $clips_removeNote,
- $clips_create,
- $clips_delete,
- $clips_list,
- $clips_notes,
- $clips_show,
- $clips_update,
- $clips_favorite,
- $clips_unfavorite,
- $clips_myFavorites,
- $drive,
- $drive_files,
- $drive_files_attachedNotes,
- $drive_files_checkExistence,
- $drive_files_create,
- $drive_files_delete,
- $drive_files_findByHash,
- $drive_files_find,
- $drive_files_show,
- $drive_files_update,
- $drive_files_uploadFromUrl,
- $drive_folders,
- $drive_folders_create,
- $drive_folders_delete,
- $drive_folders_find,
- $drive_folders_show,
- $drive_folders_update,
- $drive_stream,
- $emailAddress_available,
- $endpoint,
- $endpoints,
- $exportCustomEmojis,
- $federation_followers,
- $federation_following,
- $federation_instances,
- $federation_showInstance,
- $federation_updateRemoteUser,
- $federation_users,
- $federation_stats,
- $following_create,
- $following_delete,
- $following_update,
- $following_update_all,
- $following_invalidate,
- $following_requests_accept,
- $following_requests_cancel,
- $following_requests_list,
- $following_requests_reject,
- $gallery_featured,
- $gallery_popular,
- $gallery_posts,
- $gallery_posts_create,
- $gallery_posts_delete,
- $gallery_posts_like,
- $gallery_posts_show,
- $gallery_posts_unlike,
- $gallery_posts_update,
- $getOnlineUsersCount,
- $getAvatarDecorations,
- $hashtags_list,
- $hashtags_search,
- $hashtags_show,
- $hashtags_trend,
- $hashtags_users,
- $i,
- $i_2fa_done,
- $i_2fa_keyDone,
- $i_2fa_passwordLess,
- $i_2fa_registerKey,
- $i_2fa_register,
- $i_2fa_updateKey,
- $i_2fa_removeKey,
- $i_2fa_unregister,
- $i_apps,
- $i_authorizedApps,
- $i_claimAchievement,
- $i_changePassword,
- $i_deleteAccount,
- $i_exportBlocking,
- $i_exportFollowing,
- $i_exportMute,
- $i_exportNotes,
- $i_exportClips,
- $i_exportFavorites,
- $i_exportUserLists,
- $i_exportAntennas,
- $i_favorites,
- $i_gallery_likes,
- $i_gallery_posts,
- $i_importBlocking,
- $i_importFollowing,
- $i_importMuting,
- $i_importUserLists,
- $i_importAntennas,
- $i_notifications,
- $i_notificationsGrouped,
- $i_pageLikes,
- $i_pages,
- $i_pin,
- $i_readAllUnreadNotes,
- $i_readAnnouncement,
- $i_regenerateToken,
- $i_registry_getAll,
- $i_registry_getDetail,
- $i_registry_get,
- $i_registry_keysWithType,
- $i_registry_keys,
- $i_registry_remove,
- $i_registry_scopesWithDomain,
- $i_registry_set,
- $i_revokeToken,
- $i_signinHistory,
- $i_unpin,
- $i_updateEmail,
- $i_update,
- $i_move,
- $i_webhooks_create,
- $i_webhooks_list,
- $i_webhooks_show,
- $i_webhooks_update,
- $i_webhooks_delete,
- $i_webhooks_test,
- $invite_create,
- $invite_delete,
- $invite_list,
- $invite_limit,
- $meta,
- $emojis,
- $emoji,
- $miauth_genToken,
- $mute_create,
- $mute_delete,
- $mute_list,
- $renoteMute_create,
- $renoteMute_delete,
- $renoteMute_list,
- $my_apps,
- $notes,
- $notes_children,
- $notes_clips,
- $notes_conversation,
- $notes_create,
- $notes_delete,
- $notes_favorites_create,
- $notes_favorites_delete,
- $notes_featured,
- $notes_globalTimeline,
- $notes_hybridTimeline,
- $notes_localTimeline,
- $notes_mentions,
- $notes_polls_recommendation,
- $notes_polls_vote,
- $notes_reactions,
- $notes_reactions_create,
- $notes_reactions_delete,
- $notes_renotes,
- $notes_replies,
- $notes_searchByTag,
- $notes_search,
- $notes_show,
- $notes_state,
- $notes_threadMuting_create,
- $notes_threadMuting_delete,
- $notes_timeline,
- $notes_translate,
- $notes_unrenote,
- $notes_userListTimeline,
- $notifications_create,
- $notifications_flush,
- $notifications_markAllAsRead,
- $notifications_testNotification,
- $pagePush,
- $pages_create,
- $pages_delete,
- $pages_featured,
- $pages_like,
- $pages_show,
- $pages_unlike,
- $pages_update,
- $flash_create,
- $flash_delete,
- $flash_featured,
- $flash_like,
- $flash_show,
- $flash_unlike,
- $flash_update,
- $flash_my,
- $flash_myLikes,
- $ping,
- $pinnedUsers,
- $promo_read,
- $roles_list,
- $roles_show,
- $roles_users,
- $roles_notes,
- $requestResetPassword,
- $resetDb,
- $resetPassword,
- $serverInfo,
- $stats,
- $sw_register,
- $sw_unregister,
- $test,
- $username_available,
- $users,
- $users_clips,
- $users_followers,
- $users_following,
- $users_gallery_posts,
- $users_getFrequentlyRepliedUsers,
- $users_featuredNotes,
- $users_lists_create,
- $users_lists_delete,
- $users_lists_list,
- $users_lists_pull,
- $users_lists_push,
- $users_lists_show,
- $users_lists_update,
- $users_lists_favorite,
- $users_lists_unfavorite,
- $users_lists_createFromPublic,
- $users_lists_updateMembership,
- $users_lists_getMemberships,
- $users_notes,
- $users_pages,
- $users_flashs,
- $users_reactions,
- $users_recommendation,
- $users_relation,
- $users_reportAbuse,
- $users_searchByUsernameAndHost,
- $users_search,
- $users_show,
- $users_achievements,
- $users_updateMemo,
- $fetchRss,
- $fetchExternalResources,
- $retention,
- $bubbleGame_register,
- $bubbleGame_ranking,
- $reversi_cancelMatch,
- $reversi_games,
- $reversi_match,
- $reversi_invitations,
- $reversi_showGame,
- $reversi_surrender,
- $reversi_verify,
+ ...endpointProviders,
],
})
export class EndpointsModule {}
diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts
new file mode 100644
index 0000000000..28f7cfea04
--- /dev/null
+++ b/packages/backend/src/server/api/endpoint-list.ts
@@ -0,0 +1,399 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+/*
+ * This file contains list of all endpoints exported as pathname of API endpoint
+ *
+ * When you add new endpoint, you should add it to this file.
+ * This file is used to generate API documentation and EndpointsModule.
+ */
+
+export * as 'admin/abuse-report/notification-recipient/create' from './endpoints/admin/abuse-report/notification-recipient/create.js';
+export * as 'admin/abuse-report/notification-recipient/delete' from './endpoints/admin/abuse-report/notification-recipient/delete.js';
+export * as 'admin/abuse-report/notification-recipient/list' from './endpoints/admin/abuse-report/notification-recipient/list.js';
+export * as 'admin/abuse-report/notification-recipient/show' from './endpoints/admin/abuse-report/notification-recipient/show.js';
+export * as 'admin/abuse-report/notification-recipient/update' from './endpoints/admin/abuse-report/notification-recipient/update.js';
+export * as 'admin/abuse-user-reports' from './endpoints/admin/abuse-user-reports.js';
+export * as 'admin/accounts/create' from './endpoints/admin/accounts/create.js';
+export * as 'admin/accounts/delete' from './endpoints/admin/accounts/delete.js';
+export * as 'admin/accounts/find-by-email' from './endpoints/admin/accounts/find-by-email.js';
+export * as 'admin/ad/create' from './endpoints/admin/ad/create.js';
+export * as 'admin/ad/delete' from './endpoints/admin/ad/delete.js';
+export * as 'admin/ad/list' from './endpoints/admin/ad/list.js';
+export * as 'admin/ad/update' from './endpoints/admin/ad/update.js';
+export * as 'admin/announcements/create' from './endpoints/admin/announcements/create.js';
+export * as 'admin/announcements/delete' from './endpoints/admin/announcements/delete.js';
+export * as 'admin/announcements/list' from './endpoints/admin/announcements/list.js';
+export * as 'admin/announcements/update' from './endpoints/admin/announcements/update.js';
+export * as 'admin/avatar-decorations/create' from './endpoints/admin/avatar-decorations/create.js';
+export * as 'admin/avatar-decorations/delete' from './endpoints/admin/avatar-decorations/delete.js';
+export * as 'admin/avatar-decorations/list' from './endpoints/admin/avatar-decorations/list.js';
+export * as 'admin/avatar-decorations/update' from './endpoints/admin/avatar-decorations/update.js';
+export * as 'admin/captcha/current' from './endpoints/admin/captcha/current.js';
+export * as 'admin/captcha/save' from './endpoints/admin/captcha/save.js';
+export * as 'admin/delete-account' from './endpoints/admin/delete-account.js';
+export * as 'admin/delete-all-files-of-a-user' from './endpoints/admin/delete-all-files-of-a-user.js';
+export * as 'admin/drive/clean-remote-files' from './endpoints/admin/drive/clean-remote-files.js';
+export * as 'admin/drive/cleanup' from './endpoints/admin/drive/cleanup.js';
+export * as 'admin/drive/files' from './endpoints/admin/drive/files.js';
+export * as 'admin/drive/show-file' from './endpoints/admin/drive/show-file.js';
+export * as 'admin/emoji/add' from './endpoints/admin/emoji/add.js';
+export * as 'admin/emoji/add-aliases-bulk' from './endpoints/admin/emoji/add-aliases-bulk.js';
+export * as 'admin/emoji/copy' from './endpoints/admin/emoji/copy.js';
+export * as 'admin/emoji/delete' from './endpoints/admin/emoji/delete.js';
+export * as 'admin/emoji/delete-bulk' from './endpoints/admin/emoji/delete-bulk.js';
+export * as 'admin/emoji/import-zip' from './endpoints/admin/emoji/import-zip.js';
+export * as 'admin/emoji/list' from './endpoints/admin/emoji/list.js';
+export * as 'admin/emoji/list-remote' from './endpoints/admin/emoji/list-remote.js';
+export * as 'admin/emoji/remove-aliases-bulk' from './endpoints/admin/emoji/remove-aliases-bulk.js';
+export * as 'admin/emoji/set-aliases-bulk' from './endpoints/admin/emoji/set-aliases-bulk.js';
+export * as 'admin/emoji/set-category-bulk' from './endpoints/admin/emoji/set-category-bulk.js';
+export * as 'admin/emoji/set-license-bulk' from './endpoints/admin/emoji/set-license-bulk.js';
+export * as 'admin/emoji/update' from './endpoints/admin/emoji/update.js';
+export * as 'admin/federation/delete-all-files' from './endpoints/admin/federation/delete-all-files.js';
+export * as 'admin/federation/refresh-remote-instance-metadata' from './endpoints/admin/federation/refresh-remote-instance-metadata.js';
+export * as 'admin/federation/remove-all-following' from './endpoints/admin/federation/remove-all-following.js';
+export * as 'admin/federation/update-instance' from './endpoints/admin/federation/update-instance.js';
+export * as 'admin/forward-abuse-user-report' from './endpoints/admin/forward-abuse-user-report.js';
+export * as 'admin/get-index-stats' from './endpoints/admin/get-index-stats.js';
+export * as 'admin/get-table-stats' from './endpoints/admin/get-table-stats.js';
+export * as 'admin/get-user-ips' from './endpoints/admin/get-user-ips.js';
+export * as 'admin/invite/create' from './endpoints/admin/invite/create.js';
+export * as 'admin/invite/list' from './endpoints/admin/invite/list.js';
+export * as 'admin/meta' from './endpoints/admin/meta.js';
+export * as 'admin/promo/create' from './endpoints/admin/promo/create.js';
+export * as 'admin/queue/clear' from './endpoints/admin/queue/clear.js';
+export * as 'admin/queue/deliver-delayed' from './endpoints/admin/queue/deliver-delayed.js';
+export * as 'admin/queue/inbox-delayed' from './endpoints/admin/queue/inbox-delayed.js';
+export * as 'admin/queue/promote' from './endpoints/admin/queue/promote.js';
+export * as 'admin/queue/stats' from './endpoints/admin/queue/stats.js';
+export * as 'admin/relays/add' from './endpoints/admin/relays/add.js';
+export * as 'admin/relays/list' from './endpoints/admin/relays/list.js';
+export * as 'admin/relays/remove' from './endpoints/admin/relays/remove.js';
+export * as 'admin/reset-password' from './endpoints/admin/reset-password.js';
+export * as 'admin/resolve-abuse-user-report' from './endpoints/admin/resolve-abuse-user-report.js';
+export * as 'admin/roles/assign' from './endpoints/admin/roles/assign.js';
+export * as 'admin/roles/create' from './endpoints/admin/roles/create.js';
+export * as 'admin/roles/delete' from './endpoints/admin/roles/delete.js';
+export * as 'admin/roles/list' from './endpoints/admin/roles/list.js';
+export * as 'admin/roles/show' from './endpoints/admin/roles/show.js';
+export * as 'admin/roles/unassign' from './endpoints/admin/roles/unassign.js';
+export * as 'admin/roles/update' from './endpoints/admin/roles/update.js';
+export * as 'admin/roles/update-default-policies' from './endpoints/admin/roles/update-default-policies.js';
+export * as 'admin/roles/users' from './endpoints/admin/roles/users.js';
+export * as 'admin/send-email' from './endpoints/admin/send-email.js';
+export * as 'admin/server-info' from './endpoints/admin/server-info.js';
+export * as 'admin/show-moderation-logs' from './endpoints/admin/show-moderation-logs.js';
+export * as 'admin/show-user' from './endpoints/admin/show-user.js';
+export * as 'admin/show-users' from './endpoints/admin/show-users.js';
+export * as 'admin/suspend-user' from './endpoints/admin/suspend-user.js';
+export * as 'admin/system-webhook/create' from './endpoints/admin/system-webhook/create.js';
+export * as 'admin/system-webhook/delete' from './endpoints/admin/system-webhook/delete.js';
+export * as 'admin/system-webhook/list' from './endpoints/admin/system-webhook/list.js';
+export * as 'admin/system-webhook/show' from './endpoints/admin/system-webhook/show.js';
+export * as 'admin/system-webhook/test' from './endpoints/admin/system-webhook/test.js';
+export * as 'admin/system-webhook/update' from './endpoints/admin/system-webhook/update.js';
+export * as 'admin/unset-user-avatar' from './endpoints/admin/unset-user-avatar.js';
+export * as 'admin/unset-user-banner' from './endpoints/admin/unset-user-banner.js';
+export * as 'admin/unsuspend-user' from './endpoints/admin/unsuspend-user.js';
+export * as 'admin/update-abuse-user-report' from './endpoints/admin/update-abuse-user-report.js';
+export * as 'admin/update-meta' from './endpoints/admin/update-meta.js';
+export * as 'admin/update-user-note' from './endpoints/admin/update-user-note.js';
+export * as 'announcements' from './endpoints/announcements.js';
+export * as 'announcements/show' from './endpoints/announcements/show.js';
+export * as 'antennas/create' from './endpoints/antennas/create.js';
+export * as 'antennas/delete' from './endpoints/antennas/delete.js';
+export * as 'antennas/list' from './endpoints/antennas/list.js';
+export * as 'antennas/notes' from './endpoints/antennas/notes.js';
+export * as 'antennas/show' from './endpoints/antennas/show.js';
+export * as 'antennas/update' from './endpoints/antennas/update.js';
+export * as 'ap/get' from './endpoints/ap/get.js';
+export * as 'ap/show' from './endpoints/ap/show.js';
+export * as 'app/create' from './endpoints/app/create.js';
+export * as 'app/show' from './endpoints/app/show.js';
+export * as 'auth/accept' from './endpoints/auth/accept.js';
+export * as 'auth/session/generate' from './endpoints/auth/session/generate.js';
+export * as 'auth/session/show' from './endpoints/auth/session/show.js';
+export * as 'auth/session/userkey' from './endpoints/auth/session/userkey.js';
+export * as 'blocking/create' from './endpoints/blocking/create.js';
+export * as 'blocking/delete' from './endpoints/blocking/delete.js';
+export * as 'blocking/list' from './endpoints/blocking/list.js';
+export * as 'bubble-game/ranking' from './endpoints/bubble-game/ranking.js';
+export * as 'bubble-game/register' from './endpoints/bubble-game/register.js';
+export * as 'channels/create' from './endpoints/channels/create.js';
+export * as 'channels/favorite' from './endpoints/channels/favorite.js';
+export * as 'channels/featured' from './endpoints/channels/featured.js';
+export * as 'channels/follow' from './endpoints/channels/follow.js';
+export * as 'channels/followed' from './endpoints/channels/followed.js';
+export * as 'channels/my-favorites' from './endpoints/channels/my-favorites.js';
+export * as 'channels/owned' from './endpoints/channels/owned.js';
+export * as 'channels/search' from './endpoints/channels/search.js';
+export * as 'channels/show' from './endpoints/channels/show.js';
+export * as 'channels/timeline' from './endpoints/channels/timeline.js';
+export * as 'channels/unfavorite' from './endpoints/channels/unfavorite.js';
+export * as 'channels/unfollow' from './endpoints/channels/unfollow.js';
+export * as 'channels/update' from './endpoints/channels/update.js';
+export * as 'charts/active-users' from './endpoints/charts/active-users.js';
+export * as 'charts/ap-request' from './endpoints/charts/ap-request.js';
+export * as 'charts/drive' from './endpoints/charts/drive.js';
+export * as 'charts/federation' from './endpoints/charts/federation.js';
+export * as 'charts/instance' from './endpoints/charts/instance.js';
+export * as 'charts/notes' from './endpoints/charts/notes.js';
+export * as 'charts/user/drive' from './endpoints/charts/user/drive.js';
+export * as 'charts/user/following' from './endpoints/charts/user/following.js';
+export * as 'charts/user/notes' from './endpoints/charts/user/notes.js';
+export * as 'charts/user/pv' from './endpoints/charts/user/pv.js';
+export * as 'charts/user/reactions' from './endpoints/charts/user/reactions.js';
+export * as 'charts/users' from './endpoints/charts/users.js';
+export * as 'clips/add-note' from './endpoints/clips/add-note.js';
+export * as 'clips/create' from './endpoints/clips/create.js';
+export * as 'clips/delete' from './endpoints/clips/delete.js';
+export * as 'clips/favorite' from './endpoints/clips/favorite.js';
+export * as 'clips/list' from './endpoints/clips/list.js';
+export * as 'clips/my-favorites' from './endpoints/clips/my-favorites.js';
+export * as 'clips/notes' from './endpoints/clips/notes.js';
+export * as 'clips/remove-note' from './endpoints/clips/remove-note.js';
+export * as 'clips/show' from './endpoints/clips/show.js';
+export * as 'clips/unfavorite' from './endpoints/clips/unfavorite.js';
+export * as 'clips/update' from './endpoints/clips/update.js';
+export * as 'drive' from './endpoints/drive.js';
+export * as 'drive/files' from './endpoints/drive/files.js';
+export * as 'drive/files/attached-notes' from './endpoints/drive/files/attached-notes.js';
+export * as 'drive/files/check-existence' from './endpoints/drive/files/check-existence.js';
+export * as 'drive/files/create' from './endpoints/drive/files/create.js';
+export * as 'drive/files/delete' from './endpoints/drive/files/delete.js';
+export * as 'drive/files/find' from './endpoints/drive/files/find.js';
+export * as 'drive/files/find-by-hash' from './endpoints/drive/files/find-by-hash.js';
+export * as 'drive/files/show' from './endpoints/drive/files/show.js';
+export * as 'drive/files/update' from './endpoints/drive/files/update.js';
+export * as 'drive/files/upload-from-url' from './endpoints/drive/files/upload-from-url.js';
+export * as 'drive/folders' from './endpoints/drive/folders.js';
+export * as 'drive/folders/create' from './endpoints/drive/folders/create.js';
+export * as 'drive/folders/delete' from './endpoints/drive/folders/delete.js';
+export * as 'drive/folders/find' from './endpoints/drive/folders/find.js';
+export * as 'drive/folders/show' from './endpoints/drive/folders/show.js';
+export * as 'drive/folders/update' from './endpoints/drive/folders/update.js';
+export * as 'drive/stream' from './endpoints/drive/stream.js';
+export * as 'email-address/available' from './endpoints/email-address/available.js';
+export * as 'emoji' from './endpoints/emoji.js';
+export * as 'emojis' from './endpoints/emojis.js';
+export * as 'endpoint' from './endpoints/endpoint.js';
+export * as 'endpoints' from './endpoints/endpoints.js';
+export * as 'export-custom-emojis' from './endpoints/export-custom-emojis.js';
+export * as 'federation/followers' from './endpoints/federation/followers.js';
+export * as 'federation/following' from './endpoints/federation/following.js';
+export * as 'federation/instances' from './endpoints/federation/instances.js';
+export * as 'federation/show-instance' from './endpoints/federation/show-instance.js';
+export * as 'federation/stats' from './endpoints/federation/stats.js';
+export * as 'federation/update-remote-user' from './endpoints/federation/update-remote-user.js';
+export * as 'federation/users' from './endpoints/federation/users.js';
+export * as 'fetch-external-resources' from './endpoints/fetch-external-resources.js';
+export * as 'fetch-rss' from './endpoints/fetch-rss.js';
+export * as 'flash/create' from './endpoints/flash/create.js';
+export * as 'flash/delete' from './endpoints/flash/delete.js';
+export * as 'flash/featured' from './endpoints/flash/featured.js';
+export * as 'flash/like' from './endpoints/flash/like.js';
+export * as 'flash/my' from './endpoints/flash/my.js';
+export * as 'flash/my-likes' from './endpoints/flash/my-likes.js';
+export * as 'flash/show' from './endpoints/flash/show.js';
+export * as 'flash/unlike' from './endpoints/flash/unlike.js';
+export * as 'flash/update' from './endpoints/flash/update.js';
+export * as 'following/create' from './endpoints/following/create.js';
+export * as 'following/delete' from './endpoints/following/delete.js';
+export * as 'following/invalidate' from './endpoints/following/invalidate.js';
+export * as 'following/requests/accept' from './endpoints/following/requests/accept.js';
+export * as 'following/requests/cancel' from './endpoints/following/requests/cancel.js';
+export * as 'following/requests/list' from './endpoints/following/requests/list.js';
+export * as 'following/requests/reject' from './endpoints/following/requests/reject.js';
+export * as 'following/requests/sent' from './endpoints/following/requests/sent.js';
+export * as 'following/update' from './endpoints/following/update.js';
+export * as 'following/update-all' from './endpoints/following/update-all.js';
+export * as 'gallery/featured' from './endpoints/gallery/featured.js';
+export * as 'gallery/popular' from './endpoints/gallery/popular.js';
+export * as 'gallery/posts' from './endpoints/gallery/posts.js';
+export * as 'gallery/posts/create' from './endpoints/gallery/posts/create.js';
+export * as 'gallery/posts/delete' from './endpoints/gallery/posts/delete.js';
+export * as 'gallery/posts/like' from './endpoints/gallery/posts/like.js';
+export * as 'gallery/posts/show' from './endpoints/gallery/posts/show.js';
+export * as 'gallery/posts/unlike' from './endpoints/gallery/posts/unlike.js';
+export * as 'gallery/posts/update' from './endpoints/gallery/posts/update.js';
+export * as 'get-avatar-decorations' from './endpoints/get-avatar-decorations.js';
+export * as 'get-online-users-count' from './endpoints/get-online-users-count.js';
+export * as 'hashtags/list' from './endpoints/hashtags/list.js';
+export * as 'hashtags/search' from './endpoints/hashtags/search.js';
+export * as 'hashtags/show' from './endpoints/hashtags/show.js';
+export * as 'hashtags/trend' from './endpoints/hashtags/trend.js';
+export * as 'hashtags/users' from './endpoints/hashtags/users.js';
+export * as 'i' from './endpoints/i.js';
+export * as 'i/2fa/done' from './endpoints/i/2fa/done.js';
+export * as 'i/2fa/key-done' from './endpoints/i/2fa/key-done.js';
+export * as 'i/2fa/password-less' from './endpoints/i/2fa/password-less.js';
+export * as 'i/2fa/register' from './endpoints/i/2fa/register.js';
+export * as 'i/2fa/register-key' from './endpoints/i/2fa/register-key.js';
+export * as 'i/2fa/remove-key' from './endpoints/i/2fa/remove-key.js';
+export * as 'i/2fa/unregister' from './endpoints/i/2fa/unregister.js';
+export * as 'i/2fa/update-key' from './endpoints/i/2fa/update-key.js';
+export * as 'i/apps' from './endpoints/i/apps.js';
+export * as 'i/authorized-apps' from './endpoints/i/authorized-apps.js';
+export * as 'i/change-password' from './endpoints/i/change-password.js';
+export * as 'i/claim-achievement' from './endpoints/i/claim-achievement.js';
+export * as 'i/delete-account' from './endpoints/i/delete-account.js';
+export * as 'i/export-antennas' from './endpoints/i/export-antennas.js';
+export * as 'i/export-blocking' from './endpoints/i/export-blocking.js';
+export * as 'i/export-clips' from './endpoints/i/export-clips.js';
+export * as 'i/export-favorites' from './endpoints/i/export-favorites.js';
+export * as 'i/export-following' from './endpoints/i/export-following.js';
+export * as 'i/export-mute' from './endpoints/i/export-mute.js';
+export * as 'i/export-notes' from './endpoints/i/export-notes.js';
+export * as 'i/export-user-lists' from './endpoints/i/export-user-lists.js';
+export * as 'i/favorites' from './endpoints/i/favorites.js';
+export * as 'i/gallery/likes' from './endpoints/i/gallery/likes.js';
+export * as 'i/gallery/posts' from './endpoints/i/gallery/posts.js';
+export * as 'i/import-antennas' from './endpoints/i/import-antennas.js';
+export * as 'i/import-blocking' from './endpoints/i/import-blocking.js';
+export * as 'i/import-following' from './endpoints/i/import-following.js';
+export * as 'i/import-muting' from './endpoints/i/import-muting.js';
+export * as 'i/import-user-lists' from './endpoints/i/import-user-lists.js';
+export * as 'i/move' from './endpoints/i/move.js';
+export * as 'i/notifications' from './endpoints/i/notifications.js';
+export * as 'i/notifications-grouped' from './endpoints/i/notifications-grouped.js';
+export * as 'i/page-likes' from './endpoints/i/page-likes.js';
+export * as 'i/pages' from './endpoints/i/pages.js';
+export * as 'i/pin' from './endpoints/i/pin.js';
+export * as 'i/read-all-unread-notes' from './endpoints/i/read-all-unread-notes.js';
+export * as 'i/read-announcement' from './endpoints/i/read-announcement.js';
+export * as 'i/regenerate-token' from './endpoints/i/regenerate-token.js';
+export * as 'i/registry/get' from './endpoints/i/registry/get.js';
+export * as 'i/registry/get-all' from './endpoints/i/registry/get-all.js';
+export * as 'i/registry/get-detail' from './endpoints/i/registry/get-detail.js';
+export * as 'i/registry/keys' from './endpoints/i/registry/keys.js';
+export * as 'i/registry/keys-with-type' from './endpoints/i/registry/keys-with-type.js';
+export * as 'i/registry/remove' from './endpoints/i/registry/remove.js';
+export * as 'i/registry/scopes-with-domain' from './endpoints/i/registry/scopes-with-domain.js';
+export * as 'i/registry/set' from './endpoints/i/registry/set.js';
+export * as 'i/revoke-token' from './endpoints/i/revoke-token.js';
+export * as 'i/signin-history' from './endpoints/i/signin-history.js';
+export * as 'i/unpin' from './endpoints/i/unpin.js';
+export * as 'i/update' from './endpoints/i/update.js';
+export * as 'i/update-email' from './endpoints/i/update-email.js';
+export * as 'i/webhooks/create' from './endpoints/i/webhooks/create.js';
+export * as 'i/webhooks/delete' from './endpoints/i/webhooks/delete.js';
+export * as 'i/webhooks/list' from './endpoints/i/webhooks/list.js';
+export * as 'i/webhooks/show' from './endpoints/i/webhooks/show.js';
+export * as 'i/webhooks/test' from './endpoints/i/webhooks/test.js';
+export * as 'i/webhooks/update' from './endpoints/i/webhooks/update.js';
+export * as 'invite/create' from './endpoints/invite/create.js';
+export * as 'invite/delete' from './endpoints/invite/delete.js';
+export * as 'invite/limit' from './endpoints/invite/limit.js';
+export * as 'invite/list' from './endpoints/invite/list.js';
+export * as 'meta' from './endpoints/meta.js';
+export * as 'miauth/gen-token' from './endpoints/miauth/gen-token.js';
+export * as 'mute/create' from './endpoints/mute/create.js';
+export * as 'mute/delete' from './endpoints/mute/delete.js';
+export * as 'mute/list' from './endpoints/mute/list.js';
+export * as 'my/apps' from './endpoints/my/apps.js';
+export * as 'notes' from './endpoints/notes.js';
+export * as 'notes/children' from './endpoints/notes/children.js';
+export * as 'notes/clips' from './endpoints/notes/clips.js';
+export * as 'notes/conversation' from './endpoints/notes/conversation.js';
+export * as 'notes/create' from './endpoints/notes/create.js';
+export * as 'notes/delete' from './endpoints/notes/delete.js';
+export * as 'notes/favorites/create' from './endpoints/notes/favorites/create.js';
+export * as 'notes/favorites/delete' from './endpoints/notes/favorites/delete.js';
+export * as 'notes/featured' from './endpoints/notes/featured.js';
+export * as 'notes/global-timeline' from './endpoints/notes/global-timeline.js';
+export * as 'notes/hybrid-timeline' from './endpoints/notes/hybrid-timeline.js';
+export * as 'notes/local-timeline' from './endpoints/notes/local-timeline.js';
+export * as 'notes/mentions' from './endpoints/notes/mentions.js';
+export * as 'notes/polls/recommendation' from './endpoints/notes/polls/recommendation.js';
+export * as 'notes/polls/vote' from './endpoints/notes/polls/vote.js';
+export * as 'notes/reactions' from './endpoints/notes/reactions.js';
+export * as 'notes/reactions/create' from './endpoints/notes/reactions/create.js';
+export * as 'notes/reactions/delete' from './endpoints/notes/reactions/delete.js';
+export * as 'notes/renotes' from './endpoints/notes/renotes.js';
+export * as 'notes/replies' from './endpoints/notes/replies.js';
+export * as 'notes/search' from './endpoints/notes/search.js';
+export * as 'notes/search-by-tag' from './endpoints/notes/search-by-tag.js';
+export * as 'notes/show' from './endpoints/notes/show.js';
+export * as 'notes/state' from './endpoints/notes/state.js';
+export * as 'notes/thread-muting/create' from './endpoints/notes/thread-muting/create.js';
+export * as 'notes/thread-muting/delete' from './endpoints/notes/thread-muting/delete.js';
+export * as 'notes/timeline' from './endpoints/notes/timeline.js';
+export * as 'notes/translate' from './endpoints/notes/translate.js';
+export * as 'notes/unrenote' from './endpoints/notes/unrenote.js';
+export * as 'notes/user-list-timeline' from './endpoints/notes/user-list-timeline.js';
+export * as 'notifications/create' from './endpoints/notifications/create.js';
+export * as 'notifications/flush' from './endpoints/notifications/flush.js';
+export * as 'notifications/mark-all-as-read' from './endpoints/notifications/mark-all-as-read.js';
+export * as 'notifications/test-notification' from './endpoints/notifications/test-notification.js';
+export * as 'page-push' from './endpoints/page-push.js';
+export * as 'pages/create' from './endpoints/pages/create.js';
+export * as 'pages/delete' from './endpoints/pages/delete.js';
+export * as 'pages/featured' from './endpoints/pages/featured.js';
+export * as 'pages/like' from './endpoints/pages/like.js';
+export * as 'pages/show' from './endpoints/pages/show.js';
+export * as 'pages/unlike' from './endpoints/pages/unlike.js';
+export * as 'pages/update' from './endpoints/pages/update.js';
+export * as 'ping' from './endpoints/ping.js';
+export * as 'pinned-users' from './endpoints/pinned-users.js';
+export * as 'promo/read' from './endpoints/promo/read.js';
+export * as 'renote-mute/create' from './endpoints/renote-mute/create.js';
+export * as 'renote-mute/delete' from './endpoints/renote-mute/delete.js';
+export * as 'renote-mute/list' from './endpoints/renote-mute/list.js';
+export * as 'request-reset-password' from './endpoints/request-reset-password.js';
+export * as 'reset-db' from './endpoints/reset-db.js';
+export * as 'reset-password' from './endpoints/reset-password.js';
+export * as 'retention' from './endpoints/retention.js';
+export * as 'reversi/cancel-match' from './endpoints/reversi/cancel-match.js';
+export * as 'reversi/games' from './endpoints/reversi/games.js';
+export * as 'reversi/invitations' from './endpoints/reversi/invitations.js';
+export * as 'reversi/match' from './endpoints/reversi/match.js';
+export * as 'reversi/show-game' from './endpoints/reversi/show-game.js';
+export * as 'reversi/surrender' from './endpoints/reversi/surrender.js';
+export * as 'reversi/verify' from './endpoints/reversi/verify.js';
+export * as 'roles/list' from './endpoints/roles/list.js';
+export * as 'roles/notes' from './endpoints/roles/notes.js';
+export * as 'roles/show' from './endpoints/roles/show.js';
+export * as 'roles/users' from './endpoints/roles/users.js';
+export * as 'server-info' from './endpoints/server-info.js';
+export * as 'stats' from './endpoints/stats.js';
+export * as 'sw/register' from './endpoints/sw/register.js';
+export * as 'sw/show-registration' from './endpoints/sw/show-registration.js';
+export * as 'sw/unregister' from './endpoints/sw/unregister.js';
+export * as 'sw/update-registration' from './endpoints/sw/update-registration.js';
+export * as 'test' from './endpoints/test.js';
+export * as 'username/available' from './endpoints/username/available.js';
+export * as 'users' from './endpoints/users.js';
+export * as 'users/achievements' from './endpoints/users/achievements.js';
+export * as 'users/clips' from './endpoints/users/clips.js';
+export * as 'users/featured-notes' from './endpoints/users/featured-notes.js';
+export * as 'users/flashs' from './endpoints/users/flashs.js';
+export * as 'users/followers' from './endpoints/users/followers.js';
+export * as 'users/following' from './endpoints/users/following.js';
+export * as 'users/gallery/posts' from './endpoints/users/gallery/posts.js';
+export * as 'users/get-frequently-replied-users' from './endpoints/users/get-frequently-replied-users.js';
+export * as 'users/lists/create' from './endpoints/users/lists/create.js';
+export * as 'users/lists/create-from-public' from './endpoints/users/lists/create-from-public.js';
+export * as 'users/lists/delete' from './endpoints/users/lists/delete.js';
+export * as 'users/lists/favorite' from './endpoints/users/lists/favorite.js';
+export * as 'users/lists/get-memberships' from './endpoints/users/lists/get-memberships.js';
+export * as 'users/lists/list' from './endpoints/users/lists/list.js';
+export * as 'users/lists/pull' from './endpoints/users/lists/pull.js';
+export * as 'users/lists/push' from './endpoints/users/lists/push.js';
+export * as 'users/lists/show' from './endpoints/users/lists/show.js';
+export * as 'users/lists/unfavorite' from './endpoints/users/lists/unfavorite.js';
+export * as 'users/lists/update' from './endpoints/users/lists/update.js';
+export * as 'users/lists/update-membership' from './endpoints/users/lists/update-membership.js';
+export * as 'users/notes' from './endpoints/users/notes.js';
+export * as 'users/pages' from './endpoints/users/pages.js';
+export * as 'users/reactions' from './endpoints/users/reactions.js';
+export * as 'users/recommendation' from './endpoints/users/recommendation.js';
+export * as 'users/relation' from './endpoints/users/relation.js';
+export * as 'users/report-abuse' from './endpoints/users/report-abuse.js';
+export * as 'users/search' from './endpoints/users/search.js';
+export * as 'users/search-by-username-and-host' from './endpoints/users/search-by-username-and-host.js';
+export * as 'users/show' from './endpoints/users/show.js';
+export * as 'users/update-memo' from './endpoints/users/update-memo.js';
+export * as 'v2/admin/emoji/list' from './endpoints/v2/admin/emoji/list.js';
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index 15809b2678..a9a2ebc041 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -6,783 +6,7 @@
import { permissions } from 'misskey-js';
import type { KeyOf, Schema } from '@/misc/json-schema.js';
-import * as ep___admin_abuseReport_notificationRecipient_list
- from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js';
-import * as ep___admin_abuseReport_notificationRecipient_show
- from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js';
-import * as ep___admin_abuseReport_notificationRecipient_create
- from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js';
-import * as ep___admin_abuseReport_notificationRecipient_update
- from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js';
-import * as ep___admin_abuseReport_notificationRecipient_delete
- from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js';
-import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js';
-import * as ep___admin_meta from './endpoints/admin/meta.js';
-import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js';
-import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js';
-import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js';
-import * as ep___admin_ad_create from './endpoints/admin/ad/create.js';
-import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js';
-import * as ep___admin_ad_list from './endpoints/admin/ad/list.js';
-import * as ep___admin_ad_update from './endpoints/admin/ad/update.js';
-import * as ep___admin_announcements_create from './endpoints/admin/announcements/create.js';
-import * as ep___admin_announcements_delete from './endpoints/admin/announcements/delete.js';
-import * as ep___admin_announcements_list from './endpoints/admin/announcements/list.js';
-import * as ep___admin_announcements_update from './endpoints/admin/announcements/update.js';
-import * as ep___admin_avatarDecorations_create from './endpoints/admin/avatar-decorations/create.js';
-import * as ep___admin_avatarDecorations_delete from './endpoints/admin/avatar-decorations/delete.js';
-import * as ep___admin_avatarDecorations_list from './endpoints/admin/avatar-decorations/list.js';
-import * as ep___admin_avatarDecorations_update from './endpoints/admin/avatar-decorations/update.js';
-import * as ep___admin_deleteAllFilesOfAUser from './endpoints/admin/delete-all-files-of-a-user.js';
-import * as ep___admin_unsetUserAvatar from './endpoints/admin/unset-user-avatar.js';
-import * as ep___admin_unsetUserBanner from './endpoints/admin/unset-user-banner.js';
-import * as ep___admin_drive_cleanRemoteFiles from './endpoints/admin/drive/clean-remote-files.js';
-import * as ep___admin_drive_cleanup from './endpoints/admin/drive/cleanup.js';
-import * as ep___admin_drive_files from './endpoints/admin/drive/files.js';
-import * as ep___admin_drive_showFile from './endpoints/admin/drive/show-file.js';
-import * as ep___admin_emoji_addAliasesBulk from './endpoints/admin/emoji/add-aliases-bulk.js';
-import * as ep___admin_emoji_add from './endpoints/admin/emoji/add.js';
-import * as ep___admin_emoji_copy from './endpoints/admin/emoji/copy.js';
-import * as ep___admin_emoji_deleteBulk from './endpoints/admin/emoji/delete-bulk.js';
-import * as ep___admin_emoji_delete from './endpoints/admin/emoji/delete.js';
-import * as ep___admin_emoji_importZip from './endpoints/admin/emoji/import-zip.js';
-import * as ep___admin_emoji_listRemote from './endpoints/admin/emoji/list-remote.js';
-import * as ep___admin_emoji_list from './endpoints/admin/emoji/list.js';
-import * as ep___admin_emoji_removeAliasesBulk from './endpoints/admin/emoji/remove-aliases-bulk.js';
-import * as ep___admin_emoji_setAliasesBulk from './endpoints/admin/emoji/set-aliases-bulk.js';
-import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-category-bulk.js';
-import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js';
-import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js';
-import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js';
-import * as ep___admin_federation_refreshRemoteInstanceMetadata
- from './endpoints/admin/federation/refresh-remote-instance-metadata.js';
-import * as ep___admin_federation_removeAllFollowing from './endpoints/admin/federation/remove-all-following.js';
-import * as ep___admin_federation_updateInstance from './endpoints/admin/federation/update-instance.js';
-import * as ep___admin_getIndexStats from './endpoints/admin/get-index-stats.js';
-import * as ep___admin_getTableStats from './endpoints/admin/get-table-stats.js';
-import * as ep___admin_getUserIps from './endpoints/admin/get-user-ips.js';
-import * as ep___admin_invite_create from './endpoints/admin/invite/create.js';
-import * as ep___admin_invite_list from './endpoints/admin/invite/list.js';
-import * as ep___admin_promo_create from './endpoints/admin/promo/create.js';
-import * as ep___admin_queue_clear from './endpoints/admin/queue/clear.js';
-import * as ep___admin_queue_deliverDelayed from './endpoints/admin/queue/deliver-delayed.js';
-import * as ep___admin_queue_inboxDelayed from './endpoints/admin/queue/inbox-delayed.js';
-import * as ep___admin_queue_promote from './endpoints/admin/queue/promote.js';
-import * as ep___admin_queue_stats from './endpoints/admin/queue/stats.js';
-import * as ep___admin_relays_add from './endpoints/admin/relays/add.js';
-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';
-import * as ep___admin_showUser from './endpoints/admin/show-user.js';
-import * as ep___admin_showUsers from './endpoints/admin/show-users.js';
-import * as ep___admin_suspendUser from './endpoints/admin/suspend-user.js';
-import * as ep___admin_unsuspendUser from './endpoints/admin/unsuspend-user.js';
-import * as ep___admin_updateMeta from './endpoints/admin/update-meta.js';
-import * as ep___admin_deleteAccount from './endpoints/admin/delete-account.js';
-import * as ep___admin_updateUserNote from './endpoints/admin/update-user-note.js';
-import * as ep___admin_roles_create from './endpoints/admin/roles/create.js';
-import * as ep___admin_roles_delete from './endpoints/admin/roles/delete.js';
-import * as ep___admin_roles_list from './endpoints/admin/roles/list.js';
-import * as ep___admin_roles_show from './endpoints/admin/roles/show.js';
-import * as ep___admin_roles_update from './endpoints/admin/roles/update.js';
-import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js';
-import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js';
-import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js';
-import * as ep___admin_roles_users from './endpoints/admin/roles/users.js';
-import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js';
-import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js';
-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';
-import * as ep___antennas_delete from './endpoints/antennas/delete.js';
-import * as ep___antennas_list from './endpoints/antennas/list.js';
-import * as ep___antennas_notes from './endpoints/antennas/notes.js';
-import * as ep___antennas_show from './endpoints/antennas/show.js';
-import * as ep___antennas_update from './endpoints/antennas/update.js';
-import * as ep___ap_get from './endpoints/ap/get.js';
-import * as ep___ap_show from './endpoints/ap/show.js';
-import * as ep___app_create from './endpoints/app/create.js';
-import * as ep___app_show from './endpoints/app/show.js';
-import * as ep___auth_accept from './endpoints/auth/accept.js';
-import * as ep___auth_session_generate from './endpoints/auth/session/generate.js';
-import * as ep___auth_session_show from './endpoints/auth/session/show.js';
-import * as ep___auth_session_userkey from './endpoints/auth/session/userkey.js';
-import * as ep___blocking_create from './endpoints/blocking/create.js';
-import * as ep___blocking_delete from './endpoints/blocking/delete.js';
-import * as ep___blocking_list from './endpoints/blocking/list.js';
-import * as ep___channels_create from './endpoints/channels/create.js';
-import * as ep___channels_featured from './endpoints/channels/featured.js';
-import * as ep___channels_follow from './endpoints/channels/follow.js';
-import * as ep___channels_followed from './endpoints/channels/followed.js';
-import * as ep___channels_owned from './endpoints/channels/owned.js';
-import * as ep___channels_show from './endpoints/channels/show.js';
-import * as ep___channels_timeline from './endpoints/channels/timeline.js';
-import * as ep___channels_unfollow from './endpoints/channels/unfollow.js';
-import * as ep___channels_update from './endpoints/channels/update.js';
-import * as ep___channels_favorite from './endpoints/channels/favorite.js';
-import * as ep___channels_unfavorite from './endpoints/channels/unfavorite.js';
-import * as ep___channels_myFavorites from './endpoints/channels/my-favorites.js';
-import * as ep___channels_search from './endpoints/channels/search.js';
-import * as ep___charts_activeUsers from './endpoints/charts/active-users.js';
-import * as ep___charts_apRequest from './endpoints/charts/ap-request.js';
-import * as ep___charts_drive from './endpoints/charts/drive.js';
-import * as ep___charts_federation from './endpoints/charts/federation.js';
-import * as ep___charts_instance from './endpoints/charts/instance.js';
-import * as ep___charts_notes from './endpoints/charts/notes.js';
-import * as ep___charts_user_drive from './endpoints/charts/user/drive.js';
-import * as ep___charts_user_following from './endpoints/charts/user/following.js';
-import * as ep___charts_user_notes from './endpoints/charts/user/notes.js';
-import * as ep___charts_user_pv from './endpoints/charts/user/pv.js';
-import * as ep___charts_user_reactions from './endpoints/charts/user/reactions.js';
-import * as ep___charts_users from './endpoints/charts/users.js';
-import * as ep___clips_addNote from './endpoints/clips/add-note.js';
-import * as ep___clips_removeNote from './endpoints/clips/remove-note.js';
-import * as ep___clips_create from './endpoints/clips/create.js';
-import * as ep___clips_delete from './endpoints/clips/delete.js';
-import * as ep___clips_list from './endpoints/clips/list.js';
-import * as ep___clips_notes from './endpoints/clips/notes.js';
-import * as ep___clips_show from './endpoints/clips/show.js';
-import * as ep___clips_update from './endpoints/clips/update.js';
-import * as ep___clips_favorite from './endpoints/clips/favorite.js';
-import * as ep___clips_unfavorite from './endpoints/clips/unfavorite.js';
-import * as ep___clips_myFavorites from './endpoints/clips/my-favorites.js';
-import * as ep___drive from './endpoints/drive.js';
-import * as ep___drive_files from './endpoints/drive/files.js';
-import * as ep___drive_files_attachedNotes from './endpoints/drive/files/attached-notes.js';
-import * as ep___drive_files_checkExistence from './endpoints/drive/files/check-existence.js';
-import * as ep___drive_files_create from './endpoints/drive/files/create.js';
-import * as ep___drive_files_delete from './endpoints/drive/files/delete.js';
-import * as ep___drive_files_findByHash from './endpoints/drive/files/find-by-hash.js';
-import * as ep___drive_files_find from './endpoints/drive/files/find.js';
-import * as ep___drive_files_show from './endpoints/drive/files/show.js';
-import * as ep___drive_files_update from './endpoints/drive/files/update.js';
-import * as ep___drive_files_uploadFromUrl from './endpoints/drive/files/upload-from-url.js';
-import * as ep___drive_folders from './endpoints/drive/folders.js';
-import * as ep___drive_folders_create from './endpoints/drive/folders/create.js';
-import * as ep___drive_folders_delete from './endpoints/drive/folders/delete.js';
-import * as ep___drive_folders_find from './endpoints/drive/folders/find.js';
-import * as ep___drive_folders_show from './endpoints/drive/folders/show.js';
-import * as ep___drive_folders_update from './endpoints/drive/folders/update.js';
-import * as ep___drive_stream from './endpoints/drive/stream.js';
-import * as ep___emailAddress_available from './endpoints/email-address/available.js';
-import * as ep___endpoint from './endpoints/endpoint.js';
-import * as ep___endpoints from './endpoints/endpoints.js';
-import * as ep___exportCustomEmojis from './endpoints/export-custom-emojis.js';
-import * as ep___federation_followers from './endpoints/federation/followers.js';
-import * as ep___federation_following from './endpoints/federation/following.js';
-import * as ep___federation_instances from './endpoints/federation/instances.js';
-import * as ep___federation_showInstance from './endpoints/federation/show-instance.js';
-import * as ep___federation_updateRemoteUser from './endpoints/federation/update-remote-user.js';
-import * as ep___federation_users from './endpoints/federation/users.js';
-import * as ep___federation_stats from './endpoints/federation/stats.js';
-import * as ep___following_create from './endpoints/following/create.js';
-import * as ep___following_delete from './endpoints/following/delete.js';
-import * as ep___following_update from './endpoints/following/update.js';
-import * as ep___following_update_all from './endpoints/following/update-all.js';
-import * as ep___following_invalidate from './endpoints/following/invalidate.js';
-import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
-import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
-import * as ep___following_requests_list from './endpoints/following/requests/list.js';
-import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
-import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
-import * as ep___gallery_featured from './endpoints/gallery/featured.js';
-import * as ep___gallery_popular from './endpoints/gallery/popular.js';
-import * as ep___gallery_posts from './endpoints/gallery/posts.js';
-import * as ep___gallery_posts_create from './endpoints/gallery/posts/create.js';
-import * as ep___gallery_posts_delete from './endpoints/gallery/posts/delete.js';
-import * as ep___gallery_posts_like from './endpoints/gallery/posts/like.js';
-import * as ep___gallery_posts_show from './endpoints/gallery/posts/show.js';
-import * as ep___gallery_posts_unlike from './endpoints/gallery/posts/unlike.js';
-import * as ep___gallery_posts_update from './endpoints/gallery/posts/update.js';
-import * as ep___getOnlineUsersCount from './endpoints/get-online-users-count.js';
-import * as ep___getAvatarDecorations from './endpoints/get-avatar-decorations.js';
-import * as ep___hashtags_list from './endpoints/hashtags/list.js';
-import * as ep___hashtags_search from './endpoints/hashtags/search.js';
-import * as ep___hashtags_show from './endpoints/hashtags/show.js';
-import * as ep___hashtags_trend from './endpoints/hashtags/trend.js';
-import * as ep___hashtags_users from './endpoints/hashtags/users.js';
-import * as ep___i from './endpoints/i.js';
-import * as ep___i_2fa_done from './endpoints/i/2fa/done.js';
-import * as ep___i_2fa_keyDone from './endpoints/i/2fa/key-done.js';
-import * as ep___i_2fa_passwordLess from './endpoints/i/2fa/password-less.js';
-import * as ep___i_2fa_registerKey from './endpoints/i/2fa/register-key.js';
-import * as ep___i_2fa_register from './endpoints/i/2fa/register.js';
-import * as ep___i_2fa_updateKey from './endpoints/i/2fa/update-key.js';
-import * as ep___i_2fa_removeKey from './endpoints/i/2fa/remove-key.js';
-import * as ep___i_2fa_unregister from './endpoints/i/2fa/unregister.js';
-import * as ep___i_apps from './endpoints/i/apps.js';
-import * as ep___i_authorizedApps from './endpoints/i/authorized-apps.js';
-import * as ep___i_claimAchievement from './endpoints/i/claim-achievement.js';
-import * as ep___i_changePassword from './endpoints/i/change-password.js';
-import * as ep___i_deleteAccount from './endpoints/i/delete-account.js';
-import * as ep___i_exportBlocking from './endpoints/i/export-blocking.js';
-import * as ep___i_exportFollowing from './endpoints/i/export-following.js';
-import * as ep___i_exportMute from './endpoints/i/export-mute.js';
-import * as ep___i_exportNotes from './endpoints/i/export-notes.js';
-import * as ep___i_exportClips from './endpoints/i/export-clips.js';
-import * as ep___i_exportFavorites from './endpoints/i/export-favorites.js';
-import * as ep___i_exportUserLists from './endpoints/i/export-user-lists.js';
-import * as ep___i_exportAntennas from './endpoints/i/export-antennas.js';
-import * as ep___i_favorites from './endpoints/i/favorites.js';
-import * as ep___i_gallery_likes from './endpoints/i/gallery/likes.js';
-import * as ep___i_gallery_posts from './endpoints/i/gallery/posts.js';
-import * as ep___i_importBlocking from './endpoints/i/import-blocking.js';
-import * as ep___i_importFollowing from './endpoints/i/import-following.js';
-import * as ep___i_importMuting from './endpoints/i/import-muting.js';
-import * as ep___i_importUserLists from './endpoints/i/import-user-lists.js';
-import * as ep___i_importAntennas from './endpoints/i/import-antennas.js';
-import * as ep___i_notifications from './endpoints/i/notifications.js';
-import * as ep___i_notificationsGrouped from './endpoints/i/notifications-grouped.js';
-import * as ep___i_pageLikes from './endpoints/i/page-likes.js';
-import * as ep___i_pages from './endpoints/i/pages.js';
-import * as ep___i_pin from './endpoints/i/pin.js';
-import * as ep___i_readAllUnreadNotes from './endpoints/i/read-all-unread-notes.js';
-import * as ep___i_readAnnouncement from './endpoints/i/read-announcement.js';
-import * as ep___i_regenerateToken from './endpoints/i/regenerate-token.js';
-import * as ep___i_registry_getAll from './endpoints/i/registry/get-all.js';
-import * as ep___i_registry_getDetail from './endpoints/i/registry/get-detail.js';
-import * as ep___i_registry_get from './endpoints/i/registry/get.js';
-import * as ep___i_registry_keysWithType from './endpoints/i/registry/keys-with-type.js';
-import * as ep___i_registry_keys from './endpoints/i/registry/keys.js';
-import * as ep___i_registry_remove from './endpoints/i/registry/remove.js';
-import * as ep___i_registry_scopesWithDomain from './endpoints/i/registry/scopes-with-domain.js';
-import * as ep___i_registry_set from './endpoints/i/registry/set.js';
-import * as ep___i_revokeToken from './endpoints/i/revoke-token.js';
-import * as ep___i_signinHistory from './endpoints/i/signin-history.js';
-import * as ep___i_unpin from './endpoints/i/unpin.js';
-import * as ep___i_updateEmail from './endpoints/i/update-email.js';
-import * as ep___i_update from './endpoints/i/update.js';
-import * as ep___i_move from './endpoints/i/move.js';
-import * as ep___i_webhooks_create from './endpoints/i/webhooks/create.js';
-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';
-import * as ep___invite_limit from './endpoints/invite/limit.js';
-import * as ep___meta from './endpoints/meta.js';
-import * as ep___emojis from './endpoints/emojis.js';
-import * as ep___emoji from './endpoints/emoji.js';
-import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js';
-import * as ep___mute_create from './endpoints/mute/create.js';
-import * as ep___mute_delete from './endpoints/mute/delete.js';
-import * as ep___mute_list from './endpoints/mute/list.js';
-import * as ep___renoteMute_create from './endpoints/renote-mute/create.js';
-import * as ep___renoteMute_delete from './endpoints/renote-mute/delete.js';
-import * as ep___renoteMute_list from './endpoints/renote-mute/list.js';
-import * as ep___my_apps from './endpoints/my/apps.js';
-import * as ep___notes from './endpoints/notes.js';
-import * as ep___notes_children from './endpoints/notes/children.js';
-import * as ep___notes_clips from './endpoints/notes/clips.js';
-import * as ep___notes_conversation from './endpoints/notes/conversation.js';
-import * as ep___notes_create from './endpoints/notes/create.js';
-import * as ep___notes_delete from './endpoints/notes/delete.js';
-import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js';
-import * as ep___notes_favorites_delete from './endpoints/notes/favorites/delete.js';
-import * as ep___notes_featured from './endpoints/notes/featured.js';
-import * as ep___notes_globalTimeline from './endpoints/notes/global-timeline.js';
-import * as ep___notes_hybridTimeline from './endpoints/notes/hybrid-timeline.js';
-import * as ep___notes_localTimeline from './endpoints/notes/local-timeline.js';
-import * as ep___notes_mentions from './endpoints/notes/mentions.js';
-import * as ep___notes_polls_recommendation from './endpoints/notes/polls/recommendation.js';
-import * as ep___notes_polls_vote from './endpoints/notes/polls/vote.js';
-import * as ep___notes_reactions from './endpoints/notes/reactions.js';
-import * as ep___notes_reactions_create from './endpoints/notes/reactions/create.js';
-import * as ep___notes_reactions_delete from './endpoints/notes/reactions/delete.js';
-import * as ep___notes_renotes from './endpoints/notes/renotes.js';
-import * as ep___notes_replies from './endpoints/notes/replies.js';
-import * as ep___notes_searchByTag from './endpoints/notes/search-by-tag.js';
-import * as ep___notes_search from './endpoints/notes/search.js';
-import * as ep___notes_show from './endpoints/notes/show.js';
-import * as ep___notes_state from './endpoints/notes/state.js';
-import * as ep___notes_threadMuting_create from './endpoints/notes/thread-muting/create.js';
-import * as ep___notes_threadMuting_delete from './endpoints/notes/thread-muting/delete.js';
-import * as ep___notes_timeline from './endpoints/notes/timeline.js';
-import * as ep___notes_translate from './endpoints/notes/translate.js';
-import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
-import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
-import * as ep___notifications_create from './endpoints/notifications/create.js';
-import * as ep___notifications_flush from './endpoints/notifications/flush.js';
-import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js';
-import * as ep___notifications_testNotification from './endpoints/notifications/test-notification.js';
-import * as ep___pagePush from './endpoints/page-push.js';
-import * as ep___pages_create from './endpoints/pages/create.js';
-import * as ep___pages_delete from './endpoints/pages/delete.js';
-import * as ep___pages_featured from './endpoints/pages/featured.js';
-import * as ep___pages_like from './endpoints/pages/like.js';
-import * as ep___pages_show from './endpoints/pages/show.js';
-import * as ep___pages_unlike from './endpoints/pages/unlike.js';
-import * as ep___pages_update from './endpoints/pages/update.js';
-import * as ep___flash_create from './endpoints/flash/create.js';
-import * as ep___flash_delete from './endpoints/flash/delete.js';
-import * as ep___flash_featured from './endpoints/flash/featured.js';
-import * as ep___flash_like from './endpoints/flash/like.js';
-import * as ep___flash_show from './endpoints/flash/show.js';
-import * as ep___flash_unlike from './endpoints/flash/unlike.js';
-import * as ep___flash_update from './endpoints/flash/update.js';
-import * as ep___flash_my from './endpoints/flash/my.js';
-import * as ep___flash_myLikes from './endpoints/flash/my-likes.js';
-import * as ep___ping from './endpoints/ping.js';
-import * as ep___pinnedUsers from './endpoints/pinned-users.js';
-import * as ep___promo_read from './endpoints/promo/read.js';
-import * as ep___roles_list from './endpoints/roles/list.js';
-import * as ep___roles_show from './endpoints/roles/show.js';
-import * as ep___roles_users from './endpoints/roles/users.js';
-import * as ep___roles_notes from './endpoints/roles/notes.js';
-import * as ep___requestResetPassword from './endpoints/request-reset-password.js';
-import * as ep___resetDb from './endpoints/reset-db.js';
-import * as ep___resetPassword from './endpoints/reset-password.js';
-import * as ep___serverInfo from './endpoints/server-info.js';
-import * as ep___stats from './endpoints/stats.js';
-import * as ep___sw_show_registration from './endpoints/sw/show-registration.js';
-import * as ep___sw_update_registration from './endpoints/sw/update-registration.js';
-import * as ep___sw_register from './endpoints/sw/register.js';
-import * as ep___sw_unregister from './endpoints/sw/unregister.js';
-import * as ep___test from './endpoints/test.js';
-import * as ep___username_available from './endpoints/username/available.js';
-import * as ep___users from './endpoints/users.js';
-import * as ep___users_clips from './endpoints/users/clips.js';
-import * as ep___users_followers from './endpoints/users/followers.js';
-import * as ep___users_following from './endpoints/users/following.js';
-import * as ep___users_gallery_posts from './endpoints/users/gallery/posts.js';
-import * as ep___users_getFrequentlyRepliedUsers from './endpoints/users/get-frequently-replied-users.js';
-import * as ep___users_featuredNotes from './endpoints/users/featured-notes.js';
-import * as ep___users_lists_create from './endpoints/users/lists/create.js';
-import * as ep___users_lists_delete from './endpoints/users/lists/delete.js';
-import * as ep___users_lists_list from './endpoints/users/lists/list.js';
-import * as ep___users_lists_pull from './endpoints/users/lists/pull.js';
-import * as ep___users_lists_push from './endpoints/users/lists/push.js';
-import * as ep___users_lists_show from './endpoints/users/lists/show.js';
-import * as ep___users_lists_favorite from './endpoints/users/lists/favorite.js';
-import * as ep___users_lists_unfavorite from './endpoints/users/lists/unfavorite.js';
-import * as ep___users_lists_createFromPublic from './endpoints/users/lists/create-from-public.js';
-import * as ep___users_lists_update from './endpoints/users/lists/update.js';
-import * as ep___users_lists_updateMembership from './endpoints/users/lists/update-membership.js';
-import * as ep___users_lists_getMemberships from './endpoints/users/lists/get-memberships.js';
-import * as ep___users_notes from './endpoints/users/notes.js';
-import * as ep___users_pages from './endpoints/users/pages.js';
-import * as ep___users_flashs from './endpoints/users/flashs.js';
-import * as ep___users_reactions from './endpoints/users/reactions.js';
-import * as ep___users_recommendation from './endpoints/users/recommendation.js';
-import * as ep___users_relation from './endpoints/users/relation.js';
-import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js';
-import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js';
-import * as ep___users_search from './endpoints/users/search.js';
-import * as ep___users_show from './endpoints/users/show.js';
-import * as ep___users_achievements from './endpoints/users/achievements.js';
-import * as ep___users_updateMemo from './endpoints/users/update-memo.js';
-import * as ep___fetchRss from './endpoints/fetch-rss.js';
-import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js';
-import * as ep___retention from './endpoints/retention.js';
-import * as ep___bubbleGame_register from './endpoints/bubble-game/register.js';
-import * as ep___bubbleGame_ranking from './endpoints/bubble-game/ranking.js';
-import * as ep___reversi_cancelMatch from './endpoints/reversi/cancel-match.js';
-import * as ep___reversi_games from './endpoints/reversi/games.js';
-import * as ep___reversi_match from './endpoints/reversi/match.js';
-import * as ep___reversi_invitations from './endpoints/reversi/invitations.js';
-import * as ep___reversi_showGame from './endpoints/reversi/show-game.js';
-import * as ep___reversi_surrender from './endpoints/reversi/surrender.js';
-import * as ep___reversi_verify from './endpoints/reversi/verify.js';
-
-const eps = [
- ['admin/meta', ep___admin_meta],
- ['admin/abuse-user-reports', ep___admin_abuseUserReports],
- ['admin/abuse-report/notification-recipient/list', ep___admin_abuseReport_notificationRecipient_list],
- ['admin/abuse-report/notification-recipient/show', ep___admin_abuseReport_notificationRecipient_show],
- ['admin/abuse-report/notification-recipient/create', ep___admin_abuseReport_notificationRecipient_create],
- ['admin/abuse-report/notification-recipient/update', ep___admin_abuseReport_notificationRecipient_update],
- ['admin/abuse-report/notification-recipient/delete', ep___admin_abuseReport_notificationRecipient_delete],
- ['admin/accounts/create', ep___admin_accounts_create],
- ['admin/accounts/delete', ep___admin_accounts_delete],
- ['admin/accounts/find-by-email', ep___admin_accounts_findByEmail],
- ['admin/ad/create', ep___admin_ad_create],
- ['admin/ad/delete', ep___admin_ad_delete],
- ['admin/ad/list', ep___admin_ad_list],
- ['admin/ad/update', ep___admin_ad_update],
- ['admin/announcements/create', ep___admin_announcements_create],
- ['admin/announcements/delete', ep___admin_announcements_delete],
- ['admin/announcements/list', ep___admin_announcements_list],
- ['admin/announcements/update', ep___admin_announcements_update],
- ['admin/avatar-decorations/create', ep___admin_avatarDecorations_create],
- ['admin/avatar-decorations/delete', ep___admin_avatarDecorations_delete],
- ['admin/avatar-decorations/list', ep___admin_avatarDecorations_list],
- ['admin/avatar-decorations/update', ep___admin_avatarDecorations_update],
- ['admin/delete-all-files-of-a-user', ep___admin_deleteAllFilesOfAUser],
- ['admin/unset-user-avatar', ep___admin_unsetUserAvatar],
- ['admin/unset-user-banner', ep___admin_unsetUserBanner],
- ['admin/drive/clean-remote-files', ep___admin_drive_cleanRemoteFiles],
- ['admin/drive/cleanup', ep___admin_drive_cleanup],
- ['admin/drive/files', ep___admin_drive_files],
- ['admin/drive/show-file', ep___admin_drive_showFile],
- ['admin/emoji/add-aliases-bulk', ep___admin_emoji_addAliasesBulk],
- ['admin/emoji/add', ep___admin_emoji_add],
- ['admin/emoji/copy', ep___admin_emoji_copy],
- ['admin/emoji/delete-bulk', ep___admin_emoji_deleteBulk],
- ['admin/emoji/delete', ep___admin_emoji_delete],
- ['admin/emoji/import-zip', ep___admin_emoji_importZip],
- ['admin/emoji/list-remote', ep___admin_emoji_listRemote],
- ['admin/emoji/list', ep___admin_emoji_list],
- ['admin/emoji/remove-aliases-bulk', ep___admin_emoji_removeAliasesBulk],
- ['admin/emoji/set-aliases-bulk', ep___admin_emoji_setAliasesBulk],
- ['admin/emoji/set-category-bulk', ep___admin_emoji_setCategoryBulk],
- ['admin/emoji/set-license-bulk', ep___admin_emoji_setLicenseBulk],
- ['admin/emoji/update', ep___admin_emoji_update],
- ['admin/federation/delete-all-files', ep___admin_federation_deleteAllFiles],
- ['admin/federation/refresh-remote-instance-metadata', ep___admin_federation_refreshRemoteInstanceMetadata],
- ['admin/federation/remove-all-following', ep___admin_federation_removeAllFollowing],
- ['admin/federation/update-instance', ep___admin_federation_updateInstance],
- ['admin/get-index-stats', ep___admin_getIndexStats],
- ['admin/get-table-stats', ep___admin_getTableStats],
- ['admin/get-user-ips', ep___admin_getUserIps],
- ['admin/invite/create', ep___admin_invite_create],
- ['admin/invite/list', ep___admin_invite_list],
- ['admin/promo/create', ep___admin_promo_create],
- ['admin/queue/clear', ep___admin_queue_clear],
- ['admin/queue/deliver-delayed', ep___admin_queue_deliverDelayed],
- ['admin/queue/inbox-delayed', ep___admin_queue_inboxDelayed],
- ['admin/queue/promote', ep___admin_queue_promote],
- ['admin/queue/stats', ep___admin_queue_stats],
- ['admin/relays/add', ep___admin_relays_add],
- ['admin/relays/list', ep___admin_relays_list],
- ['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],
- ['admin/show-user', ep___admin_showUser],
- ['admin/show-users', ep___admin_showUsers],
- ['admin/suspend-user', ep___admin_suspendUser],
- ['admin/unsuspend-user', ep___admin_unsuspendUser],
- ['admin/update-meta', ep___admin_updateMeta],
- ['admin/delete-account', ep___admin_deleteAccount],
- ['admin/update-user-note', ep___admin_updateUserNote],
- ['admin/roles/create', ep___admin_roles_create],
- ['admin/roles/delete', ep___admin_roles_delete],
- ['admin/roles/list', ep___admin_roles_list],
- ['admin/roles/show', ep___admin_roles_show],
- ['admin/roles/update', ep___admin_roles_update],
- ['admin/roles/assign', ep___admin_roles_assign],
- ['admin/roles/unassign', ep___admin_roles_unassign],
- ['admin/roles/update-default-policies', ep___admin_roles_updateDefaultPolicies],
- ['admin/roles/users', ep___admin_roles_users],
- ['admin/system-webhook/create', ep___admin_systemWebhook_create],
- ['admin/system-webhook/delete', ep___admin_systemWebhook_delete],
- ['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],
- ['antennas/delete', ep___antennas_delete],
- ['antennas/list', ep___antennas_list],
- ['antennas/notes', ep___antennas_notes],
- ['antennas/show', ep___antennas_show],
- ['antennas/update', ep___antennas_update],
- ['ap/get', ep___ap_get],
- ['ap/show', ep___ap_show],
- ['app/create', ep___app_create],
- ['app/show', ep___app_show],
- ['auth/accept', ep___auth_accept],
- ['auth/session/generate', ep___auth_session_generate],
- ['auth/session/show', ep___auth_session_show],
- ['auth/session/userkey', ep___auth_session_userkey],
- ['blocking/create', ep___blocking_create],
- ['blocking/delete', ep___blocking_delete],
- ['blocking/list', ep___blocking_list],
- ['channels/create', ep___channels_create],
- ['channels/featured', ep___channels_featured],
- ['channels/follow', ep___channels_follow],
- ['channels/followed', ep___channels_followed],
- ['channels/owned', ep___channels_owned],
- ['channels/show', ep___channels_show],
- ['channels/timeline', ep___channels_timeline],
- ['channels/unfollow', ep___channels_unfollow],
- ['channels/update', ep___channels_update],
- ['channels/favorite', ep___channels_favorite],
- ['channels/unfavorite', ep___channels_unfavorite],
- ['channels/my-favorites', ep___channels_myFavorites],
- ['channels/search', ep___channels_search],
- ['charts/active-users', ep___charts_activeUsers],
- ['charts/ap-request', ep___charts_apRequest],
- ['charts/drive', ep___charts_drive],
- ['charts/federation', ep___charts_federation],
- ['charts/instance', ep___charts_instance],
- ['charts/notes', ep___charts_notes],
- ['charts/user/drive', ep___charts_user_drive],
- ['charts/user/following', ep___charts_user_following],
- ['charts/user/notes', ep___charts_user_notes],
- ['charts/user/pv', ep___charts_user_pv],
- ['charts/user/reactions', ep___charts_user_reactions],
- ['charts/users', ep___charts_users],
- ['clips/add-note', ep___clips_addNote],
- ['clips/remove-note', ep___clips_removeNote],
- ['clips/create', ep___clips_create],
- ['clips/delete', ep___clips_delete],
- ['clips/list', ep___clips_list],
- ['clips/notes', ep___clips_notes],
- ['clips/show', ep___clips_show],
- ['clips/update', ep___clips_update],
- ['clips/favorite', ep___clips_favorite],
- ['clips/unfavorite', ep___clips_unfavorite],
- ['clips/my-favorites', ep___clips_myFavorites],
- ['drive', ep___drive],
- ['drive/files', ep___drive_files],
- ['drive/files/attached-notes', ep___drive_files_attachedNotes],
- ['drive/files/check-existence', ep___drive_files_checkExistence],
- ['drive/files/create', ep___drive_files_create],
- ['drive/files/delete', ep___drive_files_delete],
- ['drive/files/find-by-hash', ep___drive_files_findByHash],
- ['drive/files/find', ep___drive_files_find],
- ['drive/files/show', ep___drive_files_show],
- ['drive/files/update', ep___drive_files_update],
- ['drive/files/upload-from-url', ep___drive_files_uploadFromUrl],
- ['drive/folders', ep___drive_folders],
- ['drive/folders/create', ep___drive_folders_create],
- ['drive/folders/delete', ep___drive_folders_delete],
- ['drive/folders/find', ep___drive_folders_find],
- ['drive/folders/show', ep___drive_folders_show],
- ['drive/folders/update', ep___drive_folders_update],
- ['drive/stream', ep___drive_stream],
- ['email-address/available', ep___emailAddress_available],
- ['endpoint', ep___endpoint],
- ['endpoints', ep___endpoints],
- ['export-custom-emojis', ep___exportCustomEmojis],
- ['federation/followers', ep___federation_followers],
- ['federation/following', ep___federation_following],
- ['federation/instances', ep___federation_instances],
- ['federation/show-instance', ep___federation_showInstance],
- ['federation/update-remote-user', ep___federation_updateRemoteUser],
- ['federation/users', ep___federation_users],
- ['federation/stats', ep___federation_stats],
- ['following/create', ep___following_create],
- ['following/delete', ep___following_delete],
- ['following/update', ep___following_update],
- ['following/update-all', ep___following_update_all],
- ['following/invalidate', ep___following_invalidate],
- ['following/requests/accept', ep___following_requests_accept],
- ['following/requests/cancel', ep___following_requests_cancel],
- ['following/requests/list', ep___following_requests_list],
- ['following/requests/sent', ep___following_requests_sent],
- ['following/requests/reject', ep___following_requests_reject],
- ['gallery/featured', ep___gallery_featured],
- ['gallery/popular', ep___gallery_popular],
- ['gallery/posts', ep___gallery_posts],
- ['gallery/posts/create', ep___gallery_posts_create],
- ['gallery/posts/delete', ep___gallery_posts_delete],
- ['gallery/posts/like', ep___gallery_posts_like],
- ['gallery/posts/show', ep___gallery_posts_show],
- ['gallery/posts/unlike', ep___gallery_posts_unlike],
- ['gallery/posts/update', ep___gallery_posts_update],
- ['get-online-users-count', ep___getOnlineUsersCount],
- ['get-avatar-decorations', ep___getAvatarDecorations],
- ['hashtags/list', ep___hashtags_list],
- ['hashtags/search', ep___hashtags_search],
- ['hashtags/show', ep___hashtags_show],
- ['hashtags/trend', ep___hashtags_trend],
- ['hashtags/users', ep___hashtags_users],
- ['i', ep___i],
- ['i/2fa/done', ep___i_2fa_done],
- ['i/2fa/key-done', ep___i_2fa_keyDone],
- ['i/2fa/password-less', ep___i_2fa_passwordLess],
- ['i/2fa/register-key', ep___i_2fa_registerKey],
- ['i/2fa/register', ep___i_2fa_register],
- ['i/2fa/update-key', ep___i_2fa_updateKey],
- ['i/2fa/remove-key', ep___i_2fa_removeKey],
- ['i/2fa/unregister', ep___i_2fa_unregister],
- ['i/apps', ep___i_apps],
- ['i/authorized-apps', ep___i_authorizedApps],
- ['i/claim-achievement', ep___i_claimAchievement],
- ['i/change-password', ep___i_changePassword],
- ['i/delete-account', ep___i_deleteAccount],
- ['i/export-blocking', ep___i_exportBlocking],
- ['i/export-following', ep___i_exportFollowing],
- ['i/export-mute', ep___i_exportMute],
- ['i/export-notes', ep___i_exportNotes],
- ['i/export-clips', ep___i_exportClips],
- ['i/export-favorites', ep___i_exportFavorites],
- ['i/export-user-lists', ep___i_exportUserLists],
- ['i/export-antennas', ep___i_exportAntennas],
- ['i/favorites', ep___i_favorites],
- ['i/gallery/likes', ep___i_gallery_likes],
- ['i/gallery/posts', ep___i_gallery_posts],
- ['i/import-blocking', ep___i_importBlocking],
- ['i/import-following', ep___i_importFollowing],
- ['i/import-muting', ep___i_importMuting],
- ['i/import-user-lists', ep___i_importUserLists],
- ['i/import-antennas', ep___i_importAntennas],
- ['i/notifications', ep___i_notifications],
- ['i/notifications-grouped', ep___i_notificationsGrouped],
- ['i/page-likes', ep___i_pageLikes],
- ['i/pages', ep___i_pages],
- ['i/pin', ep___i_pin],
- ['i/read-all-unread-notes', ep___i_readAllUnreadNotes],
- ['i/read-announcement', ep___i_readAnnouncement],
- ['i/regenerate-token', ep___i_regenerateToken],
- ['i/registry/get-all', ep___i_registry_getAll],
- ['i/registry/get-detail', ep___i_registry_getDetail],
- ['i/registry/get', ep___i_registry_get],
- ['i/registry/keys-with-type', ep___i_registry_keysWithType],
- ['i/registry/keys', ep___i_registry_keys],
- ['i/registry/remove', ep___i_registry_remove],
- ['i/registry/scopes-with-domain', ep___i_registry_scopesWithDomain],
- ['i/registry/set', ep___i_registry_set],
- ['i/revoke-token', ep___i_revokeToken],
- ['i/signin-history', ep___i_signinHistory],
- ['i/unpin', ep___i_unpin],
- ['i/update-email', ep___i_updateEmail],
- ['i/update', ep___i_update],
- ['i/move', ep___i_move],
- ['i/webhooks/create', ep___i_webhooks_create],
- ['i/webhooks/list', ep___i_webhooks_list],
- ['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],
- ['invite/limit', ep___invite_limit],
- ['meta', ep___meta],
- ['emojis', ep___emojis],
- ['emoji', ep___emoji],
- ['miauth/gen-token', ep___miauth_genToken],
- ['mute/create', ep___mute_create],
- ['mute/delete', ep___mute_delete],
- ['mute/list', ep___mute_list],
- ['renote-mute/create', ep___renoteMute_create],
- ['renote-mute/delete', ep___renoteMute_delete],
- ['renote-mute/list', ep___renoteMute_list],
- ['my/apps', ep___my_apps],
- ['notes', ep___notes],
- ['notes/children', ep___notes_children],
- ['notes/clips', ep___notes_clips],
- ['notes/conversation', ep___notes_conversation],
- ['notes/create', ep___notes_create],
- ['notes/delete', ep___notes_delete],
- ['notes/favorites/create', ep___notes_favorites_create],
- ['notes/favorites/delete', ep___notes_favorites_delete],
- ['notes/featured', ep___notes_featured],
- ['notes/global-timeline', ep___notes_globalTimeline],
- ['notes/hybrid-timeline', ep___notes_hybridTimeline],
- ['notes/local-timeline', ep___notes_localTimeline],
- ['notes/mentions', ep___notes_mentions],
- ['notes/polls/recommendation', ep___notes_polls_recommendation],
- ['notes/polls/vote', ep___notes_polls_vote],
- ['notes/reactions', ep___notes_reactions],
- ['notes/reactions/create', ep___notes_reactions_create],
- ['notes/reactions/delete', ep___notes_reactions_delete],
- ['notes/renotes', ep___notes_renotes],
- ['notes/replies', ep___notes_replies],
- ['notes/search-by-tag', ep___notes_searchByTag],
- ['notes/search', ep___notes_search],
- ['notes/show', ep___notes_show],
- ['notes/state', ep___notes_state],
- ['notes/thread-muting/create', ep___notes_threadMuting_create],
- ['notes/thread-muting/delete', ep___notes_threadMuting_delete],
- ['notes/timeline', ep___notes_timeline],
- ['notes/translate', ep___notes_translate],
- ['notes/unrenote', ep___notes_unrenote],
- ['notes/user-list-timeline', ep___notes_userListTimeline],
- ['notifications/create', ep___notifications_create],
- ['notifications/flush', ep___notifications_flush],
- ['notifications/mark-all-as-read', ep___notifications_markAllAsRead],
- ['notifications/test-notification', ep___notifications_testNotification],
- ['page-push', ep___pagePush],
- ['pages/create', ep___pages_create],
- ['pages/delete', ep___pages_delete],
- ['pages/featured', ep___pages_featured],
- ['pages/like', ep___pages_like],
- ['pages/show', ep___pages_show],
- ['pages/unlike', ep___pages_unlike],
- ['pages/update', ep___pages_update],
- ['flash/create', ep___flash_create],
- ['flash/delete', ep___flash_delete],
- ['flash/featured', ep___flash_featured],
- ['flash/like', ep___flash_like],
- ['flash/show', ep___flash_show],
- ['flash/unlike', ep___flash_unlike],
- ['flash/update', ep___flash_update],
- ['flash/my', ep___flash_my],
- ['flash/my-likes', ep___flash_myLikes],
- ['ping', ep___ping],
- ['pinned-users', ep___pinnedUsers],
- ['promo/read', ep___promo_read],
- ['roles/list', ep___roles_list],
- ['roles/show', ep___roles_show],
- ['roles/users', ep___roles_users],
- ['roles/notes', ep___roles_notes],
- ['request-reset-password', ep___requestResetPassword],
- ['reset-db', ep___resetDb],
- ['reset-password', ep___resetPassword],
- ['server-info', ep___serverInfo],
- ['stats', ep___stats],
- ['sw/show-registration', ep___sw_show_registration],
- ['sw/update-registration', ep___sw_update_registration],
- ['sw/register', ep___sw_register],
- ['sw/unregister', ep___sw_unregister],
- ['test', ep___test],
- ['username/available', ep___username_available],
- ['users', ep___users],
- ['users/clips', ep___users_clips],
- ['users/followers', ep___users_followers],
- ['users/following', ep___users_following],
- ['users/gallery/posts', ep___users_gallery_posts],
- ['users/get-frequently-replied-users', ep___users_getFrequentlyRepliedUsers],
- ['users/featured-notes', ep___users_featuredNotes],
- ['users/lists/create', ep___users_lists_create],
- ['users/lists/delete', ep___users_lists_delete],
- ['users/lists/list', ep___users_lists_list],
- ['users/lists/pull', ep___users_lists_pull],
- ['users/lists/push', ep___users_lists_push],
- ['users/lists/show', ep___users_lists_show],
- ['users/lists/favorite', ep___users_lists_favorite],
- ['users/lists/unfavorite', ep___users_lists_unfavorite],
- ['users/lists/update', ep___users_lists_update],
- ['users/lists/create-from-public', ep___users_lists_createFromPublic],
- ['users/lists/update-membership', ep___users_lists_updateMembership],
- ['users/lists/get-memberships', ep___users_lists_getMemberships],
- ['users/notes', ep___users_notes],
- ['users/pages', ep___users_pages],
- ['users/flashs', ep___users_flashs],
- ['users/reactions', ep___users_reactions],
- ['users/recommendation', ep___users_recommendation],
- ['users/relation', ep___users_relation],
- ['users/report-abuse', ep___users_reportAbuse],
- ['users/search-by-username-and-host', ep___users_searchByUsernameAndHost],
- ['users/search', ep___users_search],
- ['users/show', ep___users_show],
- ['users/achievements', ep___users_achievements],
- ['users/update-memo', ep___users_updateMemo],
- ['fetch-rss', ep___fetchRss],
- ['fetch-external-resources', ep___fetchExternalResources],
- ['retention', ep___retention],
- ['bubble-game/register', ep___bubbleGame_register],
- ['bubble-game/ranking', ep___bubbleGame_ranking],
- ['reversi/cancel-match', ep___reversi_cancelMatch],
- ['reversi/games', ep___reversi_games],
- ['reversi/match', ep___reversi_match],
- ['reversi/invitations', ep___reversi_invitations],
- ['reversi/show-game', ep___reversi_showGame],
- ['reversi/surrender', ep___reversi_surrender],
- ['reversi/verify', ep___reversi_verify],
-];
+import * as endpointsObject from './endpoint-list.js';
interface IEndpointMetaBase {
readonly stability?: 'deprecated' | 'experimental' | 'stable';
@@ -906,7 +130,7 @@ export interface IEndpoint {
params: Schema;
}
-const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => {
+const endpoints: IEndpoint[] = Object.entries(endpointsObject).map(([name, ep]) => {
return {
name: name,
get meta() {
diff --git a/packages/backend/src/server/api/endpoints/admin/captcha/current.ts b/packages/backend/src/server/api/endpoints/admin/captcha/current.ts
new file mode 100644
index 0000000000..63ec740348
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/captcha/current.ts
@@ -0,0 +1,70 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { CaptchaService, supportedCaptchaProviders } from '@/core/CaptchaService.js';
+
+export const meta = {
+ tags: ['admin', 'captcha'],
+
+ requireCredential: true,
+ requireAdmin: true,
+
+ // 実態はmetaの取得であるため
+ kind: 'read:admin:meta',
+
+ res: {
+ type: 'object',
+ properties: {
+ provider: {
+ type: 'string',
+ enum: supportedCaptchaProviders,
+ },
+ hcaptcha: {
+ type: 'object',
+ properties: {
+ siteKey: { type: 'string', nullable: true },
+ secretKey: { type: 'string', nullable: true },
+ },
+ },
+ mcaptcha: {
+ type: 'object',
+ properties: {
+ siteKey: { type: 'string', nullable: true },
+ secretKey: { type: 'string', nullable: true },
+ instanceUrl: { type: 'string', nullable: true },
+ },
+ },
+ recaptcha: {
+ type: 'object',
+ properties: {
+ siteKey: { type: 'string', nullable: true },
+ secretKey: { type: 'string', nullable: true },
+ },
+ },
+ turnstile: {
+ type: 'object',
+ properties: {
+ siteKey: { type: 'string', nullable: true },
+ secretKey: { type: 'string', nullable: true },
+ },
+ },
+ },
+ },
+} as const;
+
+export const paramDef = {} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private captchaService: CaptchaService,
+ ) {
+ super(meta, paramDef, async () => {
+ return this.captchaService.get();
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/captcha/save.ts b/packages/backend/src/server/api/endpoints/admin/captcha/save.ts
new file mode 100644
index 0000000000..98ec278ebe
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/captcha/save.ts
@@ -0,0 +1,129 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { captchaErrorCodes, CaptchaService, supportedCaptchaProviders } from '@/core/CaptchaService.js';
+import { ApiError } from '@/server/api/error.js';
+
+export const meta = {
+ tags: ['admin', 'captcha'],
+
+ requireCredential: true,
+ requireAdmin: true,
+
+ // 実態はmetaの更新であるため
+ kind: 'write:admin:meta',
+
+ errors: {
+ invalidProvider: {
+ message: 'Invalid provider.',
+ code: 'INVALID_PROVIDER',
+ id: '14bf7ae1-80cc-4363-acb2-4fd61d086af0',
+ httpStatusCode: 400,
+ },
+ invalidParameters: {
+ message: 'Invalid parameters.',
+ code: 'INVALID_PARAMETERS',
+ id: '26654194-410e-44e2-b42e-460ff6f92476',
+ httpStatusCode: 400,
+ },
+ noResponseProvided: {
+ message: 'No response provided.',
+ code: 'NO_RESPONSE_PROVIDED',
+ id: '40acbba8-0937-41fb-bb3f-474514d40afe',
+ httpStatusCode: 400,
+ },
+ requestFailed: {
+ message: 'Request failed.',
+ code: 'REQUEST_FAILED',
+ id: '0f4fe2f1-2c15-4d6e-b714-efbfcde231cd',
+ httpStatusCode: 500,
+ },
+ verificationFailed: {
+ message: 'Verification failed.',
+ code: 'VERIFICATION_FAILED',
+ id: 'c41c067f-24f3-4150-84b2-b5a3ae8c2214',
+ httpStatusCode: 400,
+ },
+ unknown: {
+ message: 'unknown',
+ code: 'UNKNOWN',
+ id: 'f868d509-e257-42a9-99c1-42614b031a97',
+ httpStatusCode: 500,
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ provider: {
+ type: 'string',
+ enum: supportedCaptchaProviders,
+ },
+ captchaResult: {
+ type: 'string', nullable: true,
+ },
+ sitekey: {
+ type: 'string', nullable: true,
+ },
+ secret: {
+ type: 'string', nullable: true,
+ },
+ instanceUrl: {
+ type: 'string', nullable: true,
+ },
+ },
+ required: ['provider'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private captchaService: CaptchaService,
+ ) {
+ super(meta, paramDef, async (ps) => {
+ const result = await this.captchaService.save(ps.provider, {
+ sitekey: ps.sitekey,
+ secret: ps.secret,
+ instanceUrl: ps.instanceUrl,
+ captchaResult: ps.captchaResult,
+ });
+
+ if (!result.success) {
+ switch (result.error.code) {
+ case captchaErrorCodes.invalidProvider:
+ throw new ApiError({
+ ...meta.errors.invalidProvider,
+ message: result.error.message,
+ });
+ case captchaErrorCodes.invalidParameters:
+ throw new ApiError({
+ ...meta.errors.invalidParameters,
+ message: result.error.message,
+ });
+ case captchaErrorCodes.noResponseProvided:
+ throw new ApiError({
+ ...meta.errors.noResponseProvided,
+ message: result.error.message,
+ });
+ case captchaErrorCodes.requestFailed:
+ throw new ApiError({
+ ...meta.errors.requestFailed,
+ message: result.error.message,
+ });
+ case captchaErrorCodes.verificationFailed:
+ throw new ApiError({
+ ...meta.errors.verificationFailed,
+ message: result.error.message,
+ });
+ default:
+ throw new ApiError(meta.errors.unknown);
+ }
+ }
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
index 796f273330..53256565f6 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -9,6 +9,7 @@ import type { DriveFilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
+import { FILE_TYPE_IMAGE } from '@/const.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -24,6 +25,11 @@ export const meta = {
code: 'NO_SUCH_FILE',
id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf',
},
+ unsupportedFileType: {
+ message: 'Unsupported file type.',
+ code: 'UNSUPPORTED_FILE_TYPE',
+ id: 'f7599d96-8750-af68-1633-9575d625c1a7',
+ },
duplicateName: {
message: 'Duplicate name.',
code: 'DUPLICATE_NAME',
@@ -47,15 +53,21 @@ export const paramDef = {
nullable: true,
description: 'Use `null` to reset the category.',
},
- aliases: { type: 'array', items: {
- type: 'string',
- } },
+ aliases: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
license: { type: 'string', nullable: true },
isSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
- roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
- type: 'string',
- } },
+ roleIdsThatCanBeUsedThisEmojiAsReaction: {
+ type: 'array',
+ items: {
+ type: 'string',
+ },
+ },
},
required: ['name', 'fileId'],
} as const;
@@ -67,9 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository,
-
private customEmojiService: CustomEmojiService,
-
private emojiEntityService: EmojiEntityService,
) {
super(meta, paramDef, async (ps, me) => {
@@ -77,9 +87,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name);
if (isDuplicate) throw new ApiError(meta.errors.duplicateName);
+ if (!FILE_TYPE_IMAGE.includes(driveFile.type)) throw new ApiError(meta.errors.unsupportedFileType);
const emoji = await this.customEmojiService.add({
- driveFile,
+ originalUrl: driveFile.url,
+ publicUrl: driveFile.webpublicUrl ?? driveFile.url,
+ fileType: driveFile.webpublicType ?? driveFile.type,
name: ps.name,
category: ps.category ?? null,
aliases: ps.aliases ?? [],
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
index 975f892df9..87b58ff6f6 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
@@ -86,7 +86,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (isDuplicate) throw new ApiError(meta.errors.duplicateName);
const addedEmoji = await this.customEmojiService.add({
- driveFile,
+ originalUrl: driveFile.url,
+ publicUrl: driveFile.webpublicUrl ?? driveFile.url,
+ fileType: driveFile.webpublicType ?? driveFile.type,
name: emoji.name,
category: emoji.category,
aliases: emoji.aliases,
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 212cba5c5d..e3aaa051c1 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -79,13 +79,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
// JSON schemeのanyOfの型変換がうまくいっていないらしい
- const required = { id: ps.id, name: ps.name } as
+ const required = { id: ps.id, name: ps.name } as
| { id: MiEmoji['id']; name?: string }
| { id?: MiEmoji['id']; name: string };
const error = await this.customEmojiService.update({
...required,
- driveFile,
+ originalUrl: driveFile != null ? driveFile.url : undefined,
+ publicUrl: driveFile != null ? (driveFile.webpublicUrl ?? driveFile.url) : undefined,
+ fileType: driveFile != null ? (driveFile.webpublicType ?? driveFile.type) : undefined,
category: ps.category,
aliases: ps.aliases,
license: ps.license,
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index 24d5a7b0f1..5c2e82da88 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -19,6 +19,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { ApiError } from '../../error.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
export const meta = {
tags: ['federation'],
@@ -32,6 +33,31 @@ export const meta = {
},
errors: {
+ federationNotAllowed: {
+ message: 'Federation for this host is not allowed.',
+ code: 'FEDERATION_NOT_ALLOWED',
+ id: '974b799e-1a29-4889-b706-18d4dd93e266',
+ },
+ uriInvalid: {
+ message: 'URI is invalid.',
+ code: 'URI_INVALID',
+ id: '1a5eab56-e47b-48c2-8d5e-217b897d70db',
+ },
+ requestFailed: {
+ message: 'Request failed.',
+ code: 'REQUEST_FAILED',
+ id: '81b539cf-4f57-4b29-bc98-032c33c0792e',
+ },
+ responseInvalid: {
+ message: 'Response from remote server is invalid.',
+ code: 'RESPONSE_INVALID',
+ id: '70193c39-54f3-4813-82f0-70a680f7495b',
+ },
+ responseInvalidIdHostNotMatch: {
+ message: 'Requested URI and response URI host does not match.',
+ code: 'RESPONSE_INVALID_ID_HOST_NOT_MATCH',
+ id: 'a2c9c61a-cb72-43ab-a964-3ca5fddb410a',
+ },
noSuchObject: {
message: 'No such object.',
code: 'NO_SUCH_OBJECT',
@@ -110,7 +136,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
*/
@bindThis
private async fetchAny(uri: string, me: MiLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
- if (!this.utilityService.isFederationAllowedUri(uri)) return null;
+ if (!this.utilityService.isFederationAllowedUri(uri)) {
+ throw new ApiError(meta.errors.federationNotAllowed);
+ }
let local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(uri),
@@ -125,7 +153,40 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// リモートから一旦オブジェクトフェッチ
const resolver = this.apResolverService.createResolver();
- const object = await resolver.resolve(uri) as any;
+ const object = await resolver.resolve(uri).catch((err) => {
+ if (err instanceof IdentifiableError) {
+ switch (err.id) {
+ // resolve
+ case 'b94fd5b1-0e3b-4678-9df2-dad4cd515ab2':
+ throw new ApiError(meta.errors.uriInvalid);
+ case '0dc86cf6-7cd6-4e56-b1e6-5903d62d7ea5':
+ case 'd592da9f-822f-4d91-83d7-4ceefabcf3d2':
+ throw new ApiError(meta.errors.requestFailed);
+ case '09d79f9e-64f1-4316-9cfa-e75c4d091574':
+ throw new ApiError(meta.errors.federationNotAllowed);
+ case '72180409-793c-4973-868e-5a118eb5519b':
+ case 'ad2dc287-75c1-44c4-839d-3d2e64576675':
+ throw new ApiError(meta.errors.responseInvalid);
+ case 'fd93c2fa-69a8-440f-880b-bf178e0ec877':
+ throw new ApiError(meta.errors.responseInvalidIdHostNotMatch);
+
+ // resolveLocal
+ case '02b40cd0-fa92-4b0c-acc9-fb2ada952ab8':
+ throw new ApiError(meta.errors.uriInvalid);
+ case 'a9d946e5-d276-47f8-95fb-f04230289bb0':
+ case '06ae3170-1796-4d93-a697-2611ea6d83b6':
+ throw new ApiError(meta.errors.noSuchObject);
+ case '7a5d2fc0-94bc-4db6-b8b8-1bf24a2e23d0':
+ throw new ApiError(meta.errors.responseInvalid);
+ }
+ }
+
+ throw new ApiError(meta.errors.requestFailed);
+ });
+
+ if (object.id == null) {
+ throw new ApiError(meta.errors.responseInvalid);
+ }
// /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する
// これはDBに存在する可能性があるため再度DB検索
diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts
index 91c8597b1b..055b5cc061 100644
--- a/packages/backend/src/server/api/endpoints/i/apps.ts
+++ b/packages/backend/src/server/api/endpoints/i/apps.ts
@@ -87,7 +87,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
name: token.name ?? token.app?.name,
createdAt: this.idService.parse(token.id).date.toISOString(),
lastUsedAt: token.lastUsedAt?.toISOString(),
- permission: token.permission,
+ permission: token.app ? token.app.permission : token.permission,
})));
});
}
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index d3eeb75b27..4c72879b73 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -553,7 +553,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const html = await this.httpRequestService.getHtml(url);
const { window } = new JSDOM(html);
- const doc = window.document;
+ const doc: Document = window.document;
const myLink = `${this.config.url}/@${user.username}`;
diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts
index f11bbbcb1a..e52d9c32df 100644
--- a/packages/backend/src/server/api/endpoints/pages/update.ts
+++ b/packages/backend/src/server/api/endpoints/pages/update.ts
@@ -102,15 +102,17 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}
- await this.pagesRepository.findBy({
- id: Not(ps.pageId),
- userId: me.id,
- name: ps.name,
- }).then(result => {
- if (result.length > 0) {
- throw new ApiError(meta.errors.nameAlreadyExists);
- }
- });
+ if (ps.name != null) {
+ await this.pagesRepository.findBy({
+ id: Not(ps.pageId),
+ userId: me.id,
+ name: ps.name,
+ }).then(result => {
+ if (result.length > 0) {
+ throw new ApiError(meta.errors.nameAlreadyExists);
+ }
+ });
+ }
await this.pagesRepository.update(page.id, {
updatedAt: new Date(),
diff --git a/packages/backend/src/server/api/endpoints/v2/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/v2/admin/emoji/list.ts
new file mode 100644
index 0000000000..9426318e34
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/v2/admin/emoji/list.ts
@@ -0,0 +1,126 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
+import { CustomEmojiService, fetchEmojisHostTypes, fetchEmojisSortKeys } from '@/core/CustomEmojiService.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireRolePolicy: 'canManageCustomEmojis',
+ kind: 'read:admin:emoji',
+
+ res: {
+ type: 'object',
+ properties: {
+ emojis: {
+ type: 'array',
+ items: {
+ type: 'object',
+ ref: 'EmojiDetailedAdmin',
+ },
+ },
+ count: { type: 'integer' },
+ allCount: { type: 'integer' },
+ allPages: { type: 'integer' },
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ query: {
+ type: 'object',
+ nullable: true,
+ properties: {
+ updatedAtFrom: { type: 'string' },
+ updatedAtTo: { type: 'string' },
+ name: { type: 'string' },
+ host: { type: 'string' },
+ uri: { type: 'string' },
+ publicUrl: { type: 'string' },
+ originalUrl: { type: 'string' },
+ type: { type: 'string' },
+ aliases: { type: 'string' },
+ category: { type: 'string' },
+ license: { type: 'string' },
+ isSensitive: { type: 'boolean' },
+ localOnly: { type: 'boolean' },
+ hostType: {
+ type: 'string',
+ enum: fetchEmojisHostTypes,
+ default: 'all',
+ },
+ roleIds: {
+ type: 'array',
+ items: { type: 'string', format: 'misskey:id' },
+ },
+ },
+ },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+ page: { type: 'integer' },
+ sortKeys: {
+ type: 'array',
+ default: ['-id'],
+ items: {
+ type: 'string',
+ enum: fetchEmojisSortKeys,
+ },
+ },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private customEmojiService: CustomEmojiService,
+ private emojiEntityService: EmojiEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const q = ps.query;
+ const result = await this.customEmojiService.fetchEmojis(
+ {
+ query: {
+ updatedAtFrom: q?.updatedAtFrom,
+ updatedAtTo: q?.updatedAtTo,
+ name: q?.name,
+ host: q?.host,
+ uri: q?.uri,
+ publicUrl: q?.publicUrl,
+ type: q?.type,
+ aliases: q?.aliases,
+ category: q?.category,
+ license: q?.license,
+ isSensitive: q?.isSensitive,
+ localOnly: q?.localOnly,
+ hostType: q?.hostType,
+ roleIds: q?.roleIds,
+ },
+ sinceId: ps.sinceId,
+ untilId: ps.untilId,
+ },
+ {
+ limit: ps.limit,
+ page: ps.page,
+ sortKeys: ps.sortKeys,
+ },
+ );
+
+ return {
+ emojis: await this.emojiEntityService.packDetailedAdminMany(result.emojis),
+ count: result.count,
+ allCount: result.allCount,
+ allPages: result.allPages,
+ };
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts
index efa47a6986..3b20ec1321 100644
--- a/packages/backend/src/server/api/openapi/gen-spec.ts
+++ b/packages/backend/src/server/api/openapi/gen-spec.ts
@@ -183,7 +183,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) {
},
...(endpoint.meta.limit ? {
'429': {
- description: 'To many requests',
+ description: 'Too many requests',
content: {
'application/json': {
schema: {
diff --git a/packages/backend/src/server/api/openapi/schemas.ts b/packages/backend/src/server/api/openapi/schemas.ts
index eb854a7141..c80dda8d96 100644
--- a/packages/backend/src/server/api/openapi/schemas.ts
+++ b/packages/backend/src/server/api/openapi/schemas.ts
@@ -3,13 +3,15 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+import { deepClone } from '@/misc/clone.js';
import type { Schema } from '@/misc/json-schema.js';
import { refs } from '@/misc/json-schema.js';
export function convertSchemaToOpenApiSchema(schema: Schema, type: 'param' | 'res', includeSelfRef: boolean): any {
// optional, nullable, refはスキーマ定義に含まれないので分離しておく
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- const { optional, nullable, ref, selfRef, ...res }: any = schema;
+ const { optional, nullable, ref, selfRef, ..._res }: any = schema;
+ const res = deepClone(_res);
if (schema.type === 'object' && schema.properties) {
if (type === 'res') {
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 75bd13221f..5681311493 100644
--- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts
@@ -95,7 +95,6 @@ class HybridTimelineChannel extends Channel {
if (this.user && note.renoteId && !note.text) {
if (note.renote && Object.keys(note.renote.reactions).length > 0) {
- console.log(note.renote.reactionAndUserPairCache);
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renote, this.user.id);
note.renote.myReaction = myRenoteReaction;
}
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 1b8873214b..4c884dd314 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -317,16 +317,19 @@ export class ClientServerService {
done();
});
} else {
+ const configUrl = new URL(this.config.url);
+ const urlOriginWithoutPort = configUrl.origin.replace(/:\d+$/, '');
+
const port = (process.env.VITE_PORT ?? '5173');
fastify.register(fastifyProxy, {
- upstream: 'http://localhost:' + port,
+ upstream: urlOriginWithoutPort + ':' + port,
prefix: '/vite',
rewritePrefix: '/vite',
});
const embedPort = (process.env.EMBED_VITE_PORT ?? '5174');
fastify.register(fastifyProxy, {
- upstream: 'http://localhost:' + embedPort,
+ upstream: urlOriginWithoutPort + ':' + embedPort,
prefix: '/embed_vite',
rewritePrefix: '/embed_vite',
});
@@ -509,6 +512,7 @@ export class ClientServerService {
usernameLower: username.toLowerCase(),
host: host ?? IsNull(),
isSuspended: false,
+ requireSigninToViewContents: false,
});
return user && await this.feedService.packFeed(user);
@@ -585,7 +589,10 @@ export class ClientServerService {
reply.header('X-Robots-Tag', 'noai');
}
- const _user = await this.userEntityService.pack(user);
+ const _user = await this.userEntityService.pack(user, null, {
+ schema: 'UserDetailed',
+ userProfile: profile,
+ });
return await reply.view('user', {
user, profile, me,
@@ -868,7 +875,7 @@ export class ClientServerService {
});
if (note == null) return;
- if (note.visibility !== 'public') return;
+ if (['specified', 'followers'].includes(note.visibility)) return;
if (note.userHost != null) return;
const _note = await this.noteEntityService.pack(note, null, { detail: true });