Merge branch 'develop' into enh-15290

This commit is contained in:
かっこかり 2025-01-21 10:07:07 +09:00 committed by GitHub
commit b4935ea05e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
79 changed files with 15240 additions and 8948 deletions

View File

@ -1,47 +0,0 @@
name: "Release Manager: release RC when ready for review"
on:
pull_request:
types: [ready_for_review]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
issues: write
pull-requests: write
jobs:
check:
runs-on: ubuntu-latest
outputs:
head: ${{ steps.get_pr.outputs.head }}
base: ${{ steps.get_pr.outputs.base }}
steps:
- uses: actions/checkout@v4
# PR情報を取得
- name: Get PR
run: |
pr_json=$(gh pr view "$PR_NUMBER" --json isDraft,headRefName,baseRefName)
echo "head=$(echo $pr_json | jq -r '.headRefName')" >> $GITHUB_OUTPUT
echo "base=$(echo $pr_json | jq -r '.baseRefName')" >> $GITHUB_OUTPUT
id: get_pr
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
release:
uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v2
needs: check
if: needs.check.outputs.head == github.event.repository.default_branch && needs.check.outputs.base == vars.STABLE_BRANCH
with:
pr_number: ${{ github.event.pull_request.number }}
user: 'github-actions[bot]'
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
indent: ${{ vars.INDENT }}
draft_prerelease_channel: alpha
ready_start_prerelease_channel: beta
reset_number_on_channel_change: true
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

View File

@ -7,7 +7,8 @@
- 詳細は #14730 および `.config/example.yml` または `.config/docker_example.yml`の'Fulltext search configuration'をご参照願います. - 詳細は #14730 および `.config/example.yml` または `.config/docker_example.yml`の'Fulltext search configuration'をご参照願います.
### General ### General
- - Feat: カスタム絵文字管理画面をリニューアル #10996
* β版として公開のため、旧画面も引き続き利用可能です
### Client ### Client
- Enhance: PC画面でチャンネルが複数列で表示されるように - Enhance: PC画面でチャンネルが複数列で表示されるように
@ -20,6 +21,7 @@
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加 - Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
(Based on https://github.com/Otaku-Social/maniakey/pull/14) (Based on https://github.com/Otaku-Social/maniakey/pull/14)
- Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に - Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に
- Enhance: クエリパラメータでuiを一時的に変更できるように #15240
- Enhance: 投稿フォームの絵文字ピッカーに独立したウィンドウを使用できるように - Enhance: 投稿フォームの絵文字ピッカーに独立したウィンドウを使用できるように
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正 - Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
- Fix: サーバー情報メニューに区切り線が不足していたのを修正 - Fix: サーバー情報メニューに区切り線が不足していたのを修正
@ -40,6 +42,10 @@
- Fix: RSSウィジェットが正しく表示されない問題を修正 - Fix: RSSウィジェットが正しく表示されない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/857) (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/857)
- Fix: ワードミュートの保存失敗時にAPIエラーが握りつぶされる事があるのを修正 - Fix: ワードミュートの保存失敗時にAPIエラーが握りつぶされる事があるのを修正
- Fix: アンケートでリモートの絵文字が正しく描画できない問題の修正
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/153)
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/656)
### Server ### Server
- Enhance: pg_bigmが利用できるよう、ートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように - Enhance: pg_bigmが利用できるよう、ートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
@ -60,6 +66,7 @@
- Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正 - Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正
- Fix: 非Misskey系のソフトウェアからHTML`<ruby>`タグを含むートを受信した場合、MFMの読み仮名ルビ文法に変換して表示 - Fix: 非Misskey系のソフトウェアからHTML`<ruby>`タグを含むートを受信した場合、MFMの読み仮名ルビ文法に変換して表示
- Fix: 連合OFFで投稿されたートに対する冗長な処理を抑止 ( #15018 ) - Fix: 連合OFFで投稿されたートに対する冗長な処理を抑止 ( #15018 )
- Fix: `/api.json`のレスポンスが2回目のリクエスト以降おかしくなる問題を修正
### Misskey.js ### Misskey.js
- Feat: allow setting `binaryType` of WebSocket connection - Feat: allow setting `binaryType` of WebSocket connection

224
locales/index.d.ts vendored
View File

@ -36,6 +36,10 @@ export interface Locale extends ILocale {
* *
*/ */
"search": string; "search": string;
/**
*
*/
"reset": string;
/** /**
* *
*/ */
@ -10543,6 +10547,226 @@ export interface Locale extends ILocale {
*/ */
"native": string; "native": string;
}; };
"_gridComponent": {
"_error": {
/**
*
*/
"requiredValue": string;
/**
* 正規表現によるバリデーションはtype:textのカラムのみサポートします
*/
"columnTypeNotSupport": string;
/**
* {pattern}
*/
"patternNotMatch": ParameterizedString<"pattern">;
/**
*
*/
"notUnique": string;
};
};
"_roleSelectDialog": {
/**
*
*/
"notSelected": string;
};
"_customEmojisManager": {
"_gridCommon": {
/**
*
*/
"copySelectionRows": string;
/**
*
*/
"copySelectionRanges": string;
/**
*
*/
"deleteSelectionRows": string;
/**
*
*/
"deleteSelectionRanges": string;
/**
*
*/
"searchSettings": string;
/**
*
*/
"searchSettingCaption": string;
/**
*
*/
"sortOrder": string;
/**
*
*/
"registrationLogs": string;
/**
*
*/
"registrationLogsCaption": string;
/**
*
*/
"alertEmojisRegisterFailedTitle": string;
/**
*
*/
"alertEmojisRegisterFailedDescription": string;
};
"_logs": {
/**
*
*/
"showSuccessLogSwitch": string;
/**
*
*/
"failureLogNothing": string;
/**
*
*/
"logNothing": string;
};
"_remote": {
/**
*
*/
"importSelectionRows": string;
/**
*
*/
"importSelectionRangesRows": string;
/**
*
*/
"importEmojisButton": string;
/**
*
*/
"confirmImportEmojisTitle": string;
/**
* {count}
*/
"confirmImportEmojisDescription": ParameterizedString<"count">;
};
"_local": {
/**
*
*/
"tabTitleList": string;
/**
*
*/
"tabTitleRegister": string;
"_list": {
/**
*
*/
"emojisNothing": string;
/**
*
*/
"markAsDeleteTargetRows": string;
/**
*
*/
"markAsDeleteTargetRanges": string;
/**
*
*/
"alertUpdateEmojisNothingDescription": string;
/**
*
*/
"alertDeleteEmojisNothingDescription": string;
/**
*
*/
"confirmUpdateEmojisTitle": string;
/**
* {count}
*/
"confirmUpdateEmojisDescription": ParameterizedString<"count">;
/**
*
*/
"confirmDeleteEmojisTitle": string;
/**
* {count}
*/
"confirmDeleteEmojisDescription": ParameterizedString<"count">;
/**
*
*/
"dialogSelectRoleTitle": string;
};
"_register": {
/**
*
*/
"uploadSettingTitle": string;
/**
*
*/
"uploadSettingDescription": string;
/**
* "category"
*/
"directoryToCategoryLabel": string;
/**
* "category"
*/
"directoryToCategoryCaption": string;
/**
*
*/
"emojiInputAreaCaption": string;
/**
*
*/
"emojiInputAreaList1": string;
/**
* PCから選択する
*/
"emojiInputAreaList2": string;
/**
*
*/
"emojiInputAreaList3": string;
/**
*
*/
"confirmRegisterEmojisTitle": string;
/**
* {count}
*/
"confirmRegisterEmojisDescription": ParameterizedString<"count">;
/**
*
*/
"confirmClearEmojisTitle": string;
/**
*
*/
"confirmClearEmojisDescription": string;
/**
*
*/
"confirmUploadEmojisTitle": string;
/**
* {count}
*/
"confirmUploadEmojisDescription": ParameterizedString<"count">;
};
};
};
"_embedCodeGen": { "_embedCodeGen": {
/** /**
* *

View File

@ -5,6 +5,7 @@ introMisskey: "ようこそMisskeyは、オープンソースの分散型マ
poweredByMisskeyDescription: "{name}は、オープンソースのプラットフォーム<b>Misskey</b>のサーバーのひとつです。" poweredByMisskeyDescription: "{name}は、オープンソースのプラットフォーム<b>Misskey</b>のサーバーのひとつです。"
monthAndDay: "{month}月 {day}日" monthAndDay: "{month}月 {day}日"
search: "検索" search: "検索"
reset: "リセット"
notifications: "通知" notifications: "通知"
username: "ユーザー名" username: "ユーザー名"
password: "パスワード" password: "パスワード"
@ -2808,6 +2809,69 @@ _contextMenu:
appWithShift: "Shiftキーでアプリケーション" appWithShift: "Shiftキーでアプリケーション"
native: "ブラウザのUI" native: "ブラウザのUI"
_gridComponent:
_error:
requiredValue: "この値は必須項目です"
columnTypeNotSupport: "正規表現によるバリデーションはtype:textのカラムのみサポートします。"
patternNotMatch: "この値は{pattern}のパターンに一致しません"
notUnique: "この値は一意である必要があります"
_roleSelectDialog:
notSelected: "選択されていません"
_customEmojisManager:
_gridCommon:
copySelectionRows: "選択行をコピー"
copySelectionRanges: "選択範囲をコピー"
deleteSelectionRows: "選択行を削除"
deleteSelectionRanges: "選択範囲の行を削除"
searchSettings: "検索設定"
searchSettingCaption: "検索条件を詳細に設定します。"
sortOrder: "並び順"
registrationLogs: "登録ログ"
registrationLogsCaption: "絵文字更新・削除時のログが表示されます。更新・削除操作を行ったり、ページを遷移・リロードすると消えます。"
alertEmojisRegisterFailedTitle: "エラー"
alertEmojisRegisterFailedDescription: "絵文字の更新・削除に失敗しました。詳細は登録ログをご確認ください。"
_logs:
showSuccessLogSwitch: "成功ログを表示"
failureLogNothing: "失敗ログはありません。"
logNothing: "ログはありません。"
_remote:
importSelectionRows: "選択行をインポート"
importSelectionRangesRows: "選択範囲の行をインポート"
importEmojisButton: "チェックされた絵文字をインポート"
confirmImportEmojisTitle: "絵文字のインポート"
confirmImportEmojisDescription: "リモートから受信した{count}個の絵文字のインポートを行います。絵文字のライセンスに十分な注意を払ってください。実行しますか?"
_local:
tabTitleList: "登録済み絵文字一覧"
tabTitleRegister: "絵文字の登録"
_list:
emojisNothing: "登録された絵文字はありません。"
markAsDeleteTargetRows: "選択行を削除対象にする"
markAsDeleteTargetRanges: "選択範囲の行を削除対象にする"
alertUpdateEmojisNothingDescription: "変更された絵文字はありません。"
alertDeleteEmojisNothingDescription: "削除対象の絵文字はありません。"
confirmUpdateEmojisTitle: "確認"
confirmUpdateEmojisDescription: "{count}個の絵文字を更新します。実行しますか?"
confirmDeleteEmojisTitle: "確認"
confirmDeleteEmojisDescription: "チェックがつけられた{count}個の絵文字を削除します。実行しますか?"
dialogSelectRoleTitle: "絵文字に設定されたロールで検索"
_register:
uploadSettingTitle: "アップロード設定"
uploadSettingDescription: "この画面で絵文字アップロードを行う際の動作を設定できます。"
directoryToCategoryLabel: "ディレクトリ名を\"category\"に入力する"
directoryToCategoryCaption: "ディレクトリをドラッグ・ドロップした時に、ディレクトリ名を\"category\"に入力します。"
emojiInputAreaCaption: "いずれかの方法で登録する絵文字を選択してください。"
emojiInputAreaList1: "この枠に画像ファイルまたはディレクトリをドラッグ&ドロップ"
emojiInputAreaList2: "このリンクをクリックしてPCから選択する"
emojiInputAreaList3: "このリンクをクリックしてドライブから選択する"
confirmRegisterEmojisTitle: "確認"
confirmRegisterEmojisDescription: "リストに表示されている絵文字を新たなカスタム絵文字として登録します。よろしいですか?(負荷を避けるため、一度の操作で登録可能な絵文字は{count}件までです)"
confirmClearEmojisTitle: "確認"
confirmClearEmojisDescription: "編集内容を破棄し、リストに表示されている絵文字をクリアします。よろしいですか?"
confirmUploadEmojisTitle: "確認"
confirmUploadEmojisDescription: "ドラッグ&ドロップされた{count}個のファイルをドライブにアップロードします。実行しますか?"
_embedCodeGen: _embedCodeGen:
title: "埋め込みコードをカスタマイズ" title: "埋め込みコードをカスタマイズ"
header: "ヘッダーを表示" header: "ヘッダーを表示"

View File

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2025.1.0-beta.1", "version": "2025.1.0-beta.2",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class OptimizeEmojiIndex1709126576000 {
name = 'OptimizeEmojiIndex1709126576000'
async up(queryRunner) {
await queryRunner.query(`CREATE INDEX "IDX_EMOJI_ROLE_IDS" ON "emoji" using gin ("roleIdsThatCanBeUsedThisEmojiAsReaction")`)
await queryRunner.query(`CREATE INDEX "IDX_EMOJI_CATEGORY" ON "emoji" ("category")`)
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "IDX_EMOJI_CATEGORY"`)
await queryRunner.query(`DROP INDEX "IDX_EMOJI_ROLE_IDS"`)
}
}

View File

@ -26,6 +26,18 @@ export const DB_MAX_NOTE_TEXT_LENGTH = 8192;
export const DB_MAX_IMAGE_COMMENT_LENGTH = 512; export const DB_MAX_IMAGE_COMMENT_LENGTH = 512;
//#endregion //#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 としてレスポンスされる // ここに含まれないものは application/octet-stream としてレスポンスされる
// SVGはXSSを生むので許可しない // SVGはXSSを生むので許可しない

View File

@ -4,24 +4,59 @@
*/ */
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { In, IsNull } from 'typeorm';
import * as Redis from 'ioredis'; import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { In, IsNull } from 'typeorm';
import { IdService } from '@/core/IdService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import { IdService } from '@/core/IdService.js';
import type { MiEmoji } from '@/models/Emoji.js';
import type { EmojisRepository, MiRole, MiUser } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { MemoryKVCache, RedisSingleCache } from '@/misc/cache.js';
import { UtilityService } from '@/core/UtilityService.js';
import { query } from '@/misc/prelude/url.js';
import type { Serialized } from '@/types.js';
import { ModerationLogService } from '@/core/ModerationLogService.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 { 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';
const parseEmojiStrRegexp = /^([-\w]+)(?:@([\w.-]+))?$/; 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() @Injectable()
export class CustomEmojiService implements OnApplicationShutdown { export class CustomEmojiService implements OnApplicationShutdown {
private emojisCache: MemoryKVCache<MiEmoji | null>; private emojisCache: MemoryKVCache<MiEmoji | null>;
@ -30,10 +65,8 @@ export class CustomEmojiService implements OnApplicationShutdown {
constructor( constructor(
@Inject(DI.redis) @Inject(DI.redis)
private redisClient: Redis.Redis, private redisClient: Redis.Redis,
@Inject(DI.emojisRepository) @Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository, private emojisRepository: EmojisRepository,
private utilityService: UtilityService, private utilityService: UtilityService,
private idService: IdService, private idService: IdService,
private emojiEntityService: EmojiEntityService, private emojiEntityService: EmojiEntityService,
@ -58,7 +91,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis @bindThis
public async add(data: { public async add(data: {
driveFile: MiDriveFile; originalUrl: string;
publicUrl: string;
fileType: string;
name: string; name: string;
category: string | null; category: string | null;
aliases: string[]; aliases: string[];
@ -75,9 +110,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
category: data.category, category: data.category,
host: data.host, host: data.host,
aliases: data.aliases, aliases: data.aliases,
originalUrl: data.driveFile.url, originalUrl: data.originalUrl,
publicUrl: data.driveFile.webpublicUrl ?? data.driveFile.url, publicUrl: data.publicUrl,
type: data.driveFile.webpublicType ?? data.driveFile.type, type: data.fileType,
license: data.license, license: data.license,
isSensitive: data.isSensitive, isSensitive: data.isSensitive,
localOnly: data.localOnly, localOnly: data.localOnly,
@ -105,8 +140,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis @bindThis
public async update(data: ( public async update(data: (
{ id: MiEmoji['id'], name?: string; } | { name: string; id?: MiEmoji['id'], } { id: MiEmoji['id'], name?: string; } | { name: string; id?: MiEmoji['id'], }
) & { ) & {
driveFile?: MiDriveFile; originalUrl?: string;
publicUrl?: string;
fileType?: string;
category?: string | null; category?: string | null;
aliases?: string[]; aliases?: string[];
license?: string | null; license?: string | null;
@ -139,9 +176,9 @@ export class CustomEmojiService implements OnApplicationShutdown {
license: data.license, license: data.license,
isSensitive: data.isSensitive, isSensitive: data.isSensitive,
localOnly: data.localOnly, localOnly: data.localOnly,
originalUrl: data.driveFile != null ? data.driveFile.url : undefined, originalUrl: data.originalUrl,
publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined, publicUrl: data.publicUrl,
type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined, type: data.fileType,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined, roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined,
}); });
@ -308,7 +345,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
@bindThis @bindThis
private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null { private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null {
// クエリに使うホスト // クエリに使うホスト
let host = src === '.' ? null // .はローカルホスト (ここがマッチするのはリアクションのみ) let host = src === '.' ? null // .はローカルホスト (ここがマッチするのはリアクションのみ)
: src === undefined ? noteUserHost // ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない) : src === undefined ? noteUserHost // ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない)
: this.utilityService.isSelfHost(src) ? null // 自ホスト指定 : this.utilityService.isSelfHost(src) ? null // 自ホスト指定
@ -414,6 +451,151 @@ export class CustomEmojiService implements OnApplicationShutdown {
return this.emojisRepository.findOneBy({ name, host: IsNull() }); return this.emojisRepository.findOneBy({ name, host: IsNull() });
} }
@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 @bindThis
public dispose(): void { public dispose(): void {
this.emojisCache.dispose(); this.emojisCache.dispose();

View File

@ -558,6 +558,11 @@ const extension_context_definition = {
'_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents', '_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents',
'_misskey_makeNotesFollowersOnlyBefore': 'misskey:_misskey_makeNotesFollowersOnlyBefore', '_misskey_makeNotesFollowersOnlyBefore': 'misskey:_misskey_makeNotesFollowersOnlyBefore',
'_misskey_makeNotesHiddenBefore': 'misskey:_misskey_makeNotesHiddenBefore', '_misskey_makeNotesHiddenBefore': 'misskey:_misskey_makeNotesHiddenBefore',
'_misskey_license': 'misskey:_misskey_license',
'freeText': {
'@id': 'misskey:freeText',
'@type': 'schema:text',
},
'isCat': 'misskey:isCat', 'isCat': 'misskey:isCat',
// vcard // vcard
vcard: 'http://www.w3.org/2006/vcard/ns#', vcard: 'http://www.w3.org/2006/vcard/ns#',

View File

@ -4,10 +4,10 @@
*/ */
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js'; 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 { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
import type { MiEmoji } from '@/models/Emoji.js'; import type { MiEmoji } from '@/models/Emoji.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@ -16,6 +16,8 @@ export class EmojiEntityService {
constructor( constructor(
@Inject(DI.emojisRepository) @Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository, private emojisRepository: EmojisRepository,
@Inject(DI.rolesRepository)
private rolesRepository: RolesRepository,
) { ) {
} }
@ -68,8 +70,90 @@ export class EmojiEntityService {
@bindThis @bindThis
public packDetailedMany( public packDetailedMany(
emojis: any[], emojis: any[],
) { ): Promise<Packed<'EmojiDetailed'>[]> {
return Promise.all(emojis.map(x => this.packDetailed(x))); 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 })));
}
} }

View File

@ -33,7 +33,11 @@ import { packedClipSchema } from '@/models/json-schema/clip.js';
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js'; import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
import { packedQueueCountSchema } from '@/models/json-schema/queue.js'; import { packedQueueCountSchema } from '@/models/json-schema/queue.js';
import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.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 { packedFlashSchema } from '@/models/json-schema/flash.js';
import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js'; import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js';
import { packedSigninSchema } from '@/models/json-schema/signin.js'; import { packedSigninSchema } from '@/models/json-schema/signin.js';
@ -95,6 +99,7 @@ export const refs = {
GalleryPost: packedGalleryPostSchema, GalleryPost: packedGalleryPostSchema,
EmojiSimple: packedEmojiSimpleSchema, EmojiSimple: packedEmojiSimpleSchema,
EmojiDetailed: packedEmojiDetailedSchema, EmojiDetailed: packedEmojiDetailedSchema,
EmojiDetailedAdmin: packedEmojiDetailedAdminSchema,
Flash: packedFlashSchema, Flash: packedFlashSchema,
Signin: packedSigninSchema, Signin: packedSigninSchema,
RoleCondFormulaLogics: packedRoleCondFormulaLogicsSchema, RoleCondFormulaLogics: packedRoleCondFormulaLogicsSchema,

View File

@ -104,3 +104,86 @@ export const packedEmojiDetailedSchema = {
}, },
}, },
} as const; } 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;

View File

@ -87,6 +87,7 @@ export class ImportCustomEmojisProcessorService {
await this.emojisRepository.delete({ await this.emojisRepository.delete({
name: emojiInfo.name, name: emojiInfo.name,
}); });
try { try {
const driveFile = await this.driveService.addFile({ const driveFile = await this.driveService.addFile({
user: null, user: null,
@ -95,11 +96,13 @@ export class ImportCustomEmojisProcessorService {
force: true, force: true,
}); });
await this.customEmojiService.add({ await this.customEmojiService.add({
originalUrl: driveFile.url,
publicUrl: driveFile.webpublicUrl ?? driveFile.url,
fileType: driveFile.webpublicType ?? driveFile.type,
name: emojiInfo.name, name: emojiInfo.name,
category: emojiInfo.category, category: emojiInfo.category,
host: null, host: null,
aliases: emojiInfo.aliases, aliases: emojiInfo.aliases,
driveFile,
license: emojiInfo.license, license: emojiInfo.license,
isSensitive: emojiInfo.isSensitive, isSensitive: emojiInfo.isSensitive,
localOnly: emojiInfo.localOnly, localOnly: emojiInfo.localOnly,

View File

@ -6,9 +6,12 @@
import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js'; import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import type { SystemWebhookEventType } from '@/models/SystemWebhook.js';
import type { MiUser } from '@/models/User.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 { 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'; import type httpSignature from '@peertube/http-signature';
export type DeliverJobData = { export type DeliverJobData = {
@ -106,9 +109,9 @@ export type EndedPollNotificationJobData = {
noteId: MiNote['id']; noteId: MiNote['id'];
}; };
export type SystemWebhookDeliverJobData = { export type SystemWebhookDeliverJobData<T extends SystemWebhookEventType = SystemWebhookEventType> = {
type: string; type: T;
content: unknown; content: SystemWebhookPayload<T>;
webhookId: MiWebhook['id']; webhookId: MiWebhook['id'];
to: string; to: string;
secret: string; secret: string;
@ -116,9 +119,9 @@ export type SystemWebhookDeliverJobData = {
eventId: string; eventId: string;
}; };
export type UserWebhookDeliverJobData = { export type UserWebhookDeliverJobData<T extends WebhookEventTypes = WebhookEventTypes> = {
type: string; type: T;
content: unknown; content: UserWebhookPayload<T>;
webhookId: MiWebhook['id']; webhookId: MiWebhook['id'];
userId: MiUser['id']; userId: MiUser['id'];
to: string; to: string;

File diff suppressed because it is too large Load Diff

View File

@ -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';

View File

@ -6,787 +6,7 @@
import { permissions } from 'misskey-js'; import { permissions } from 'misskey-js';
import type { KeyOf, Schema } from '@/misc/json-schema.js'; import type { KeyOf, Schema } from '@/misc/json-schema.js';
import * as ep___admin_abuseReport_notificationRecipient_list import * as endpointsObject from './endpoint-list.js';
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_captcha_current from './endpoints/admin/captcha/current.js';
import * as ep___admin_captcha_save from './endpoints/admin/captcha/save.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/captcha/current', ep___admin_captcha_current],
['admin/captcha/save', ep___admin_captcha_save],
['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],
];
interface IEndpointMetaBase { interface IEndpointMetaBase {
readonly stability?: 'deprecated' | 'experimental' | 'stable'; readonly stability?: 'deprecated' | 'experimental' | 'stable';
@ -910,7 +130,7 @@ export interface IEndpoint {
params: Schema; params: Schema;
} }
const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => { const endpoints: IEndpoint[] = Object.entries(endpointsObject).map(([name, ep]) => {
return { return {
name: name, name: name,
get meta() { get meta() {

View File

@ -9,6 +9,7 @@ import type { DriveFilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { FILE_TYPE_IMAGE } from '@/const.js';
import { ApiError } from '../../../error.js'; import { ApiError } from '../../../error.js';
export const meta = { export const meta = {
@ -24,6 +25,11 @@ export const meta = {
code: 'NO_SUCH_FILE', code: 'NO_SUCH_FILE',
id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf', id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf',
}, },
unsupportedFileType: {
message: 'Unsupported file type.',
code: 'UNSUPPORTED_FILE_TYPE',
id: 'f7599d96-8750-af68-1633-9575d625c1a7',
},
duplicateName: { duplicateName: {
message: 'Duplicate name.', message: 'Duplicate name.',
code: 'DUPLICATE_NAME', code: 'DUPLICATE_NAME',
@ -47,15 +53,21 @@ export const paramDef = {
nullable: true, nullable: true,
description: 'Use `null` to reset the category.', description: 'Use `null` to reset the category.',
}, },
aliases: { type: 'array', items: { aliases: {
type: 'string', type: 'array',
} }, items: {
type: 'string',
},
},
license: { type: 'string', nullable: true }, license: { type: 'string', nullable: true },
isSensitive: { type: 'boolean' }, isSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' }, localOnly: { type: 'boolean' },
roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: { roleIdsThatCanBeUsedThisEmojiAsReaction: {
type: 'string', type: 'array',
} }, items: {
type: 'string',
},
},
}, },
required: ['name', 'fileId'], required: ['name', 'fileId'],
} as const; } as const;
@ -67,9 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
private customEmojiService: CustomEmojiService, private customEmojiService: CustomEmojiService,
private emojiEntityService: EmojiEntityService, private emojiEntityService: EmojiEntityService,
) { ) {
super(meta, paramDef, async (ps, me) => { 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); if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name); const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name);
if (isDuplicate) throw new ApiError(meta.errors.duplicateName); 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({ const emoji = await this.customEmojiService.add({
driveFile, originalUrl: driveFile.url,
publicUrl: driveFile.webpublicUrl ?? driveFile.url,
fileType: driveFile.webpublicType ?? driveFile.type,
name: ps.name, name: ps.name,
category: ps.category ?? null, category: ps.category ?? null,
aliases: ps.aliases ?? [], aliases: ps.aliases ?? [],

View File

@ -86,7 +86,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (isDuplicate) throw new ApiError(meta.errors.duplicateName); if (isDuplicate) throw new ApiError(meta.errors.duplicateName);
const addedEmoji = await this.customEmojiService.add({ const addedEmoji = await this.customEmojiService.add({
driveFile, originalUrl: driveFile.url,
publicUrl: driveFile.webpublicUrl ?? driveFile.url,
fileType: driveFile.webpublicType ?? driveFile.type,
name: emoji.name, name: emoji.name,
category: emoji.category, category: emoji.category,
aliases: emoji.aliases, aliases: emoji.aliases,

View File

@ -85,7 +85,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const error = await this.customEmojiService.update({ const error = await this.customEmojiService.update({
...required, ...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, category: ps.category,
aliases: ps.aliases, aliases: ps.aliases,
license: ps.license, license: ps.license,

View File

@ -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,
};
});
}
}

View File

@ -3,13 +3,15 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { deepClone } from '@/misc/clone.js';
import type { Schema } from '@/misc/json-schema.js'; import type { Schema } from '@/misc/json-schema.js';
import { refs } from '@/misc/json-schema.js'; import { refs } from '@/misc/json-schema.js';
export function convertSchemaToOpenApiSchema(schema: Schema, type: 'param' | 'res', includeSelfRef: boolean): any { export function convertSchemaToOpenApiSchema(schema: Schema, type: 'param' | 'res', includeSelfRef: boolean): any {
// optional, nullable, refはスキーマ定義に含まれないので分離しておく // optional, nullable, refはスキーマ定義に含まれないので分離しておく
// eslint-disable-next-line @typescript-eslint/no-unused-vars // 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 (schema.type === 'object' && schema.properties) {
if (type === 'res') { if (type === 'res') {

View File

@ -0,0 +1,817 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { afterEach, beforeAll, describe, test } from '@jest/globals';
import { Test, TestingModule } from '@nestjs/testing';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js';
import { GlobalModule } from '@/GlobalModule.js';
import { EmojisRepository } from '@/models/_.js';
import { MiEmoji } from '@/models/Emoji.js';
describe('CustomEmojiService', () => {
let app: TestingModule;
let service: CustomEmojiService;
let emojisRepository: EmojisRepository;
let idService: IdService;
beforeAll(async () => {
app = await Test
.createTestingModule({
imports: [
GlobalModule,
],
providers: [
CustomEmojiService,
UtilityService,
IdService,
EmojiEntityService,
ModerationLogService,
GlobalEventService,
],
})
.compile();
app.enableShutdownHooks();
service = app.get<CustomEmojiService>(CustomEmojiService);
emojisRepository = app.get<EmojisRepository>(DI.emojisRepository);
idService = app.get<IdService>(IdService);
});
describe('fetchEmojis', () => {
async function insert(data: Partial<MiEmoji>[]) {
for (const d of data) {
const id = idService.gen();
await emojisRepository.insert({
id: id,
updatedAt: new Date(),
...d,
});
}
}
function call(params: Parameters<CustomEmojiService['fetchEmojis']>['0']) {
return service.fetchEmojis(
params,
{
// テスト向けに
sortKeys: ['+id'],
},
);
}
function defaultData(suffix: string, override?: Partial<MiEmoji>): Partial<MiEmoji> {
return {
name: `emoji${suffix}`,
host: null,
category: 'default',
originalUrl: `https://example.com/emoji${suffix}.png`,
publicUrl: `https://example.com/emoji${suffix}.png`,
type: 'image/png',
aliases: [`emoji${suffix}`],
license: 'CC0',
isSensitive: false,
localOnly: false,
roleIdsThatCanBeUsedThisEmojiAsReaction: [],
...override,
};
}
afterEach(async () => {
await emojisRepository.delete({});
});
describe('単独', () => {
test('updatedAtFrom', async () => {
await insert([
defaultData('001', { updatedAt: new Date('2021-01-01T00:00:00.000Z') }),
defaultData('002', { updatedAt: new Date('2021-01-02T00:00:00.000Z') }),
defaultData('003', { updatedAt: new Date('2021-01-03T00:00:00.000Z') }),
]);
const actual = await call({
query: {
updatedAtFrom: '2021-01-02T00:00:00.000Z',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji002');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('updatedAtTo', async () => {
await insert([
defaultData('001', { updatedAt: new Date('2021-01-01T00:00:00.000Z') }),
defaultData('002', { updatedAt: new Date('2021-01-02T00:00:00.000Z') }),
defaultData('003', { updatedAt: new Date('2021-01-03T00:00:00.000Z') }),
]);
const actual = await call({
query: {
updatedAtTo: '2021-01-02T00:00:00.000Z',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
});
describe('name', () => {
test('single', async () => {
await insert([
defaultData('001'),
defaultData('002'),
]);
const actual = await call({
query: {
name: 'emoji001',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji001');
});
test('multi', async () => {
await insert([
defaultData('001'),
defaultData('002'),
]);
const actual = await call({
query: {
name: 'emoji001 emoji002',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
});
test('keyword', async () => {
await insert([
defaultData('001'),
defaultData('002'),
defaultData('003', { name: 'em003' }),
]);
const actual = await call({
query: {
name: 'oji',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
});
test('escape', async () => {
await insert([
defaultData('001'),
]);
const actual = await call({
query: {
name: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('host', () => {
test('single', async () => {
await insert([
defaultData('001', { host: 'example.com' }),
defaultData('002', { host: 'example.com' }),
defaultData('003', { host: '1.example.com' }),
defaultData('004', { host: '2.example.com' }),
]);
const actual = await call({
query: {
host: 'example.com',
hostType: 'remote',
},
});
expect(actual.allCount).toBe(4);
});
test('multi', async () => {
await insert([
defaultData('001', { host: 'example.com' }),
defaultData('002', { host: 'example.com' }),
defaultData('003', { host: '1.example.com' }),
defaultData('004', { host: '2.example.com' }),
]);
const actual = await call({
query: {
host: '1.example.com 2.example.com',
hostType: 'remote',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji003');
expect(actual.emojis[1].name).toBe('emoji004');
});
test('keyword', async () => {
await insert([
defaultData('001', { host: 'example.com' }),
defaultData('002', { host: 'example.com' }),
defaultData('003', { host: '1.example.com' }),
defaultData('004', { host: '2.example.com' }),
]);
const actual = await call({
query: {
host: 'example',
hostType: 'remote',
},
});
expect(actual.allCount).toBe(4);
});
test('escape', async () => {
await insert([
defaultData('001', { host: 'example.com' }),
]);
const actual = await call({
query: {
host: '%',
hostType: 'remote',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('uri', () => {
test('single', async () => {
await insert([
defaultData('001', { uri: 'uri001' }),
defaultData('002', { uri: 'uri002' }),
defaultData('003', { uri: 'uri003' }),
]);
const actual = await call({
query: {
uri: 'uri002',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { uri: 'uri001' }),
defaultData('002', { uri: 'uri002' }),
defaultData('003', { uri: 'uri003' }),
]);
const actual = await call({
query: {
uri: 'uri001 uri003',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('keyword', async () => {
await insert([
defaultData('001', { uri: 'uri001' }),
defaultData('002', { uri: 'uri002' }),
defaultData('003', { uri: 'uri003' }),
]);
const actual = await call({
query: {
uri: 'ri',
},
});
expect(actual.allCount).toBe(3);
});
test('escape', async () => {
await insert([
defaultData('001', { uri: 'uri001' }),
]);
const actual = await call({
query: {
uri: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('publicUrl', () => {
test('single', async () => {
await insert([
defaultData('001', { publicUrl: 'publicUrl001' }),
defaultData('002', { publicUrl: 'publicUrl002' }),
defaultData('003', { publicUrl: 'publicUrl003' }),
]);
const actual = await call({
query: {
publicUrl: 'publicUrl002',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { publicUrl: 'publicUrl001' }),
defaultData('002', { publicUrl: 'publicUrl002' }),
defaultData('003', { publicUrl: 'publicUrl003' }),
]);
const actual = await call({
query: {
publicUrl: 'publicUrl001 publicUrl003',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('keyword', async () => {
await insert([
defaultData('001', { publicUrl: 'publicUrl001' }),
defaultData('002', { publicUrl: 'publicUrl002' }),
defaultData('003', { publicUrl: 'publicUrl003' }),
]);
const actual = await call({
query: {
publicUrl: 'Url',
},
});
expect(actual.allCount).toBe(3);
});
test('escape', async () => {
await insert([
defaultData('001', { publicUrl: 'publicUrl001' }),
]);
const actual = await call({
query: {
publicUrl: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('type', () => {
test('single', async () => {
await insert([
defaultData('001', { type: 'type001' }),
defaultData('002', { type: 'type002' }),
defaultData('003', { type: 'type003' }),
]);
const actual = await call({
query: {
type: 'type002',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { type: 'type001' }),
defaultData('002', { type: 'type002' }),
defaultData('003', { type: 'type003' }),
]);
const actual = await call({
query: {
type: 'type001 type003',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('keyword', async () => {
await insert([
defaultData('001', { type: 'type001' }),
defaultData('002', { type: 'type002' }),
defaultData('003', { type: 'type003' }),
]);
const actual = await call({
query: {
type: 'pe',
},
});
expect(actual.allCount).toBe(3);
});
test('escape', async () => {
await insert([
defaultData('001', { type: 'type001' }),
]);
const actual = await call({
query: {
type: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('aliases', () => {
test('single', async () => {
await insert([
defaultData('001', { aliases: ['alias001', 'alias002'] }),
defaultData('002', { aliases: ['alias002'] }),
defaultData('003', { aliases: ['alias003'] }),
]);
const actual = await call({
query: {
aliases: 'alias002',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { aliases: ['alias001', 'alias002'] }),
defaultData('002', { aliases: ['alias002', 'alias004'] }),
defaultData('003', { aliases: ['alias003'] }),
defaultData('004', { aliases: ['alias004'] }),
]);
const actual = await call({
query: {
aliases: 'alias001 alias004',
},
});
expect(actual.allCount).toBe(3);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
expect(actual.emojis[2].name).toBe('emoji004');
});
test('keyword', async () => {
await insert([
defaultData('001', { aliases: ['alias001', 'alias002'] }),
defaultData('002', { aliases: ['alias002', 'alias004'] }),
defaultData('003', { aliases: ['alias003'] }),
defaultData('004', { aliases: ['alias004'] }),
]);
const actual = await call({
query: {
aliases: 'ias',
},
});
expect(actual.allCount).toBe(4);
});
test('escape', async () => {
await insert([
defaultData('001', { aliases: ['alias001', 'alias002'] }),
]);
const actual = await call({
query: {
aliases: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('category', () => {
test('single', async () => {
await insert([
defaultData('001', { category: 'category001' }),
defaultData('002', { category: 'category002' }),
defaultData('003', { category: 'category003' }),
]);
const actual = await call({
query: {
category: 'category002',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { category: 'category001' }),
defaultData('002', { category: 'category002' }),
defaultData('003', { category: 'category003' }),
]);
const actual = await call({
query: {
category: 'category001 category003',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('keyword', async () => {
await insert([
defaultData('001', { category: 'category001' }),
defaultData('002', { category: 'category002' }),
defaultData('003', { category: 'category003' }),
]);
const actual = await call({
query: {
category: 'egory',
},
});
expect(actual.allCount).toBe(3);
});
test('escape', async () => {
await insert([
defaultData('001', { category: 'category001' }),
]);
const actual = await call({
query: {
category: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('license', () => {
test('single', async () => {
await insert([
defaultData('001', { license: 'license001' }),
defaultData('002', { license: 'license002' }),
defaultData('003', { license: 'license003' }),
]);
const actual = await call({
query: {
license: 'license002',
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { license: 'license001' }),
defaultData('002', { license: 'license002' }),
defaultData('003', { license: 'license003' }),
]);
const actual = await call({
query: {
license: 'license001 license003',
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('keyword', async () => {
await insert([
defaultData('001', { license: 'license001' }),
defaultData('002', { license: 'license002' }),
defaultData('003', { license: 'license003' }),
]);
const actual = await call({
query: {
license: 'cense',
},
});
expect(actual.allCount).toBe(3);
});
test('escape', async () => {
await insert([
defaultData('001', { license: 'license001' }),
]);
const actual = await call({
query: {
license: '%',
},
});
expect(actual.allCount).toBe(0);
});
});
describe('isSensitive', () => {
test('true', async () => {
await insert([
defaultData('001', { isSensitive: true }),
defaultData('002', { isSensitive: false }),
defaultData('003', { isSensitive: true }),
]);
const actual = await call({
query: {
isSensitive: true,
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('false', async () => {
await insert([
defaultData('001', { isSensitive: true }),
defaultData('002', { isSensitive: false }),
defaultData('003', { isSensitive: true }),
]);
const actual = await call({
query: {
isSensitive: false,
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('null', async () => {
await insert([
defaultData('001', { isSensitive: true }),
defaultData('002', { isSensitive: false }),
defaultData('003', { isSensitive: true }),
]);
const actual = await call({
query: {},
});
expect(actual.allCount).toBe(3);
});
});
describe('localOnly', () => {
test('true', async () => {
await insert([
defaultData('001', { localOnly: true }),
defaultData('002', { localOnly: false }),
defaultData('003', { localOnly: true }),
]);
const actual = await call({
query: {
localOnly: true,
},
});
expect(actual.allCount).toBe(2);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji003');
});
test('false', async () => {
await insert([
defaultData('001', { localOnly: true }),
defaultData('002', { localOnly: false }),
defaultData('003', { localOnly: true }),
]);
const actual = await call({
query: {
localOnly: false,
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('null', async () => {
await insert([
defaultData('001', { localOnly: true }),
defaultData('002', { localOnly: false }),
defaultData('003', { localOnly: true }),
]);
const actual = await call({
query: {},
});
expect(actual.allCount).toBe(3);
});
});
describe('roleId', () => {
test('single', async () => {
await insert([
defaultData('001', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role001'] }),
defaultData('002', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role002'] }),
defaultData('003', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role003'] }),
]);
const actual = await call({
query: {
roleIds: ['role002'],
},
});
expect(actual.allCount).toBe(1);
expect(actual.emojis[0].name).toBe('emoji002');
});
test('multi', async () => {
await insert([
defaultData('001', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role001'] }),
defaultData('002', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role002', 'role003'] }),
defaultData('003', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role003'] }),
defaultData('004', { roleIdsThatCanBeUsedThisEmojiAsReaction: ['role004'] }),
]);
const actual = await call({
query: {
roleIds: ['role001', 'role003'],
},
});
expect(actual.allCount).toBe(3);
expect(actual.emojis[0].name).toBe('emoji001');
expect(actual.emojis[1].name).toBe('emoji002');
expect(actual.emojis[2].name).toBe('emoji003');
});
});
});
});
});

View File

@ -0,0 +1,154 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import seedrandom from 'seedrandom';
/**
* AIで生成した無作為なファーストネーム
*/
export const firstNameDict = [
'Ethan', 'Olivia', 'Jackson', 'Emma', 'Liam', 'Ava', 'Aiden', 'Sophia', 'Mason', 'Isabella',
'Noah', 'Mia', 'Lucas', 'Harper', 'Caleb', 'Abigail', 'Samuel', 'Emily', 'Logan',
'Madison', 'Benjamin', 'Chloe', 'Elijah', 'Grace', 'Alexander', 'Scarlett', 'William', 'Zoey', 'James', 'Lily',
]
/**
* AIで生成した無作為なラストネーム
*/
export const lastNameDict = [
'Anderson', 'Johnson', 'Thompson', 'Davis', 'Rodriguez', 'Smith', 'Patel', 'Williams', 'Lee', 'Brown',
'Garcia', 'Jackson', 'Martinez', 'Taylor', 'Harris', 'Nguyen', 'Miller', 'Jones', 'Wilson',
'White', 'Thomas', 'Garcia', 'Martinez', 'Robinson', 'Turner', 'Lewis', 'Hall', 'King', 'Baker', 'Cooper',
]
/**
* AIで生成した無作為な国名
*/
export const countryDict = [
'Japan', 'Canada', 'Brazil', 'Australia', 'Italy', 'SouthAfrica', 'Mexico', 'Sweden', 'Russia', 'India',
'Germany', 'Argentina', 'South Korea', 'France', 'Nigeria', 'Turkey', 'Spain', 'Egypt', 'Thailand',
'Vietnam', 'Kenya', 'Saudi Arabia', 'Netherlands', 'Colombia', 'Poland', 'Chile', 'Malaysia', 'Ukraine', 'New Zealand', 'Peru',
]
export function text(length: number = 10, seed?: string): string {
let result = "";
// シード値を使う場合、同じ数値が羅列されるが、ランダム文字列という意味では満たせていると思うのでこのまま使っておく
const rand = seed ? seedrandom(seed)() : Math.random();
while (result.length < length) {
result += rand.toString(36).substring(2);
}
return result.substring(0, length);
}
export function integer(min: number = 0, max: number = 9999, seed?: string): number {
const rand = seed ? seedrandom(seed)() : Math.random();
return Math.floor(rand * (max - min)) + min;
}
export function date(params?: {
yearMin?: number,
yearMax?: number,
monthMin?: number,
monthMax?: number,
dayMin?: number,
dayMax?: number,
hourMin?: number,
hourMax?: number,
minuteMin?: number,
minuteMax?: number,
secondMin?: number,
secondMax?: number,
millisecondMin?: number,
millisecondMax?: number,
}, seed?: string): Date {
const year = integer(params?.yearMin ?? 1970, params?.yearMax ?? (new Date()).getFullYear(), seed);
const month = integer(params?.monthMin ?? 1, params?.monthMax ?? 12, seed);
let day = integer(params?.dayMin ?? 1, params?.dayMax ?? 31, seed);
if (month === 2) {
day = Math.min(day, 28);
} else if ([4, 6, 9, 11].includes(month)) {
day = Math.min(day, 30);
} else {
day = Math.min(day, 31);
}
const hour = integer(params?.hourMin ?? 0, params?.hourMax ?? 23, seed);
const minute = integer(params?.minuteMin ?? 0, params?.minuteMax ?? 59, seed);
const second = integer(params?.secondMin ?? 0, params?.secondMax ?? 59, seed);
const millisecond = integer(params?.millisecondMin ?? 0, params?.millisecondMax ?? 999, seed);
return new Date(year, month - 1, day, hour, minute, second, millisecond);
}
export function boolean(seed?: string): boolean {
const rand = seed ? seedrandom(seed)() : Math.random();
return rand < 0.5;
}
export function choose<T>(array: T[], seed?: string): T {
const rand = seed ? seedrandom(seed)() : Math.random();
return array[Math.floor(rand * array.length)];
}
export function firstName(seed?: string): string {
return choose(firstNameDict, seed);
}
export function lastName(seed?: string): string {
return choose(lastNameDict, seed);
}
export function country(seed?: string): string {
return choose(countryDict, seed);
}
const TIME2000 = 946684800000;
export function fakeId(seed?: string): string {
let time = new Date().getTime();
time = time - TIME2000;
if (time < 0) time = 0;
const timeStr = time.toString(36).padStart(8, '0');
const noiseStr = text(2, seed);
return timeStr + noiseStr;
}
export function imageDataUrl(options?: {
size?: {
width?: number,
height?: number,
},
color?: {
red?: number,
green?: number,
blue?: number,
alpha?: number,
}
}, seed?: string): string {
const canvas = document.createElement('canvas');
canvas.width = options?.size?.width ?? 100;
canvas.height = options?.size?.height ?? 100;
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('Failed to get 2d context');
}
ctx.beginPath()
const red = options?.color?.red ?? integer(0, 255, seed);
const green = options?.color?.green ?? integer(0, 255, seed);
const blue = options?.color?.blue ?? integer(0, 255, seed);
const alpha = options?.color?.alpha ?? 1;
ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2, true);
ctx.fillStyle = `rgba(${red}, ${green}, ${blue}, ${alpha})`;
ctx.fill();
return canvas.toDataURL('image/png', 1.0);
}

View File

@ -5,6 +5,7 @@
import { AISCRIPT_VERSION } from '@syuilo/aiscript'; import { AISCRIPT_VERSION } from '@syuilo/aiscript';
import type { entities } from 'misskey-js' import type { entities } from 'misskey-js'
import { date, imageDataUrl, text } from "./fake-utils.js";
export function abuseUserReport() { export function abuseUserReport() {
return { return {
@ -301,3 +302,93 @@ export function inviteCode(isUsed = false, hasExpiration = false, isExpired = fa
used: isUsed, used: isUsed,
} }
} }
export function role(params: {
id?: string,
name?: string,
color?: string | null,
iconUrl?: string | null,
description?: string,
isModerator?: boolean,
isAdministrator?: boolean,
displayOrder?: number,
createdAt?: string,
updatedAt?: string,
target?: 'manual' | 'conditional',
isPublic?: boolean,
isExplorable?: boolean,
asBadge?: boolean,
canEditMembersByModerator?: boolean,
usersCount?: number,
}, seed?: string): entities.Role {
const prefix = params.displayOrder ? params.displayOrder.toString().padStart(3, '0') + '-' : '';
const genId = text(36, seed);
const createdAt = params.createdAt ?? date({}, seed).toISOString();
const updatedAt = params.updatedAt ?? date({}, seed).toISOString();
return {
id: params.id ?? genId,
name: params.name ?? `${prefix}TestRole-${genId}`,
color: params.color ?? '#445566',
iconUrl: params.iconUrl ?? null,
description: params.description ?? '',
isModerator: params.isModerator ?? false,
isAdministrator: params.isAdministrator ?? false,
displayOrder: params.displayOrder ?? 0,
createdAt: createdAt,
updatedAt: updatedAt,
target: params.target ?? 'manual',
isPublic: params.isPublic ?? true,
isExplorable: params.isExplorable ?? true,
asBadge: params.asBadge ?? true,
canEditMembersByModerator: params.canEditMembersByModerator ?? false,
usersCount: params.usersCount ?? 10,
condFormula: {
id: '',
type: 'or',
values: []
},
policies: {},
}
}
export function emoji(params?: {
id?: string,
name?: string,
host?: string,
uri?: string,
publicUrl?: string,
originalUrl?: string,
type?: string,
aliases?: string[],
category?: string,
license?: string,
isSensitive?: boolean,
localOnly?: boolean,
roleIdsThatCanBeUsedThisEmojiAsReaction?: {id:string, name:string}[],
updatedAt?: string,
}, seed?: string): entities.EmojiDetailedAdmin {
const _seed = seed ?? (params?.id ?? "DEFAULT_SEED");
const id = params?.id ?? text(32, _seed);
const name = params?.name ?? text(8, _seed);
const updatedAt = params?.updatedAt ?? date({}, _seed).toISOString();
const image = imageDataUrl({}, _seed)
return {
id: id,
name: name,
host: params?.host ?? null,
uri: params?.uri ?? null,
publicUrl: params?.publicUrl ?? image,
originalUrl: params?.originalUrl ?? image,
type: params?.type ?? 'image/png',
aliases: params?.aliases ?? [`alias1-${name}`, `alias2-${name}`],
category: params?.category ?? null,
license: params?.license ?? null,
isSensitive: params?.isSensitive ?? false,
localOnly: params?.localOnly ?? false,
roleIdsThatCanBeUsedThisEmojiAsReaction: params?.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [],
updatedAt: updatedAt,
}
}

View File

@ -416,6 +416,10 @@ function toStories(component: string): Promise<string> {
glob('src/components/MkUserSetupDialog.*.vue'), glob('src/components/MkUserSetupDialog.*.vue'),
glob('src/components/MkInstanceCardMini.vue'), glob('src/components/MkInstanceCardMini.vue'),
glob('src/components/MkInviteCode.vue'), glob('src/components/MkInviteCode.vue'),
glob('src/components/MkTagItem.vue'),
glob('src/components/MkRoleSelectDialog.vue'),
glob('src/components/grid/MkGrid.vue'),
glob('src/pages/admin/custom-emojis-manager2.vue'),
glob('src/pages/admin/overview.ap-requests.vue'), glob('src/pages/admin/overview.ap-requests.vue'),
glob('src/pages/user/home.vue'), glob('src/pages/user/home.vue'),
glob('src/pages/search.vue'), glob('src/pages/search.vue'),

View File

@ -7,6 +7,7 @@ import { createApp, defineAsyncComponent, markRaw } from 'vue';
import { ui } from '@@/js/config.js'; import { ui } from '@@/js/config.js';
import { common } from './common.js'; import { common } from './common.js';
import type * as Misskey from 'misskey-js'; import type * as Misskey from 'misskey-js';
import type { Component } from 'vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { alert, confirm, popup, post, toast } from '@/os.js'; import { alert, confirm, popup, post, toast } from '@/os.js';
import { useStream } from '@/stream.js'; import { useStream } from '@/stream.js';
@ -25,13 +26,38 @@ import { type Keymap, makeHotkey } from '@/scripts/hotkey.js';
import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js'; import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js';
export async function mainBoot() { export async function mainBoot() {
const { isClientUpdated } = await common(() => createApp( const { isClientUpdated } = await common(() => {
new URLSearchParams(window.location.search).has('zen') || (ui === 'deck' && deckStore.state.useSimpleUiForNonRootPages && location.pathname !== '/') ? defineAsyncComponent(() => import('@/ui/zen.vue')) : let uiStyle = ui;
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) : const searchParams = new URLSearchParams(window.location.search);
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) : if (!$i) uiStyle = 'visitor';
defineAsyncComponent(() => import('@/ui/universal.vue')),
)); if (searchParams.has('zen')) uiStyle = 'zen';
if (uiStyle === 'deck' && deckStore.state.useSimpleUiForNonRootPages && location.pathname !== '/') uiStyle = 'zen';
if (searchParams.has('ui')) uiStyle = searchParams.get('ui');
let rootComponent: Component;
switch (uiStyle) {
case 'zen':
rootComponent = defineAsyncComponent(() => import('@/ui/zen.vue'));
break;
case 'deck':
rootComponent = defineAsyncComponent(() => import('@/ui/deck.vue'));
break;
case 'visitor':
rootComponent = defineAsyncComponent(() => import('@/ui/visitor.vue'));
break;
case 'classic':
rootComponent = defineAsyncComponent(() => import('@/ui/classic.vue'));
break;
default:
rootComponent = defineAsyncComponent(() => import('@/ui/universal.vue'));
break;
}
return createApp(rootComponent);
});
reactionPicker.init(); reactionPicker.init();
emojiPicker.init(); emojiPicker.init();

View File

@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
> >
<KeepAlive> <KeepAlive>
<div v-show="opened"> <div v-show="opened">
<MkSpacer v-if="withSpacer" :marginMin="14" :marginMax="22"> <MkSpacer v-if="withSpacer" :marginMin="spacerMin" :marginMax="spacerMax">
<slot></slot> <slot></slot>
</MkSpacer> </MkSpacer>
<div v-else> <div v-else>
@ -64,10 +64,14 @@ const props = withDefaults(defineProps<{
defaultOpen?: boolean; defaultOpen?: boolean;
maxHeight?: number | null; maxHeight?: number | null;
withSpacer?: boolean; withSpacer?: boolean;
spacerMin?: number;
spacerMax?: number;
}>(), { }>(), {
defaultOpen: false, defaultOpen: false,
maxHeight: null, maxHeight: null,
withSpacer: true, withSpacer: true,
spacerMin: 14,
spacerMax: 22,
}); });
const rootEl = shallowRef<HTMLElement>(); const rootEl = shallowRef<HTMLElement>();

View File

@ -288,20 +288,23 @@ const align = () => {
const onOpened = () => { const onOpened = () => {
emit('opened'); emit('opened');
// NOTE: Chromatic undefined // contentnextTick
if (content.value == null) return; nextTick(() => {
// NOTE: Chromatic undefined
if (content.value == null) return;
// //
const el = content.value.children[0]; const el = content.value.children[0];
el.addEventListener('mousedown', ev => { el.addEventListener('mousedown', ev => {
contentClicking = true; contentClicking = true;
window.addEventListener('mouseup', ev => { window.addEventListener('mouseup', ev => {
// click mouseup // click mouseup
window.setTimeout(() => { window.setTimeout(() => {
contentClicking = false; contentClicking = false;
}, 100); }, 100);
}, { passive: true, once: true }); }, { passive: true, once: true });
}, { passive: true }); }, { passive: true });
});
}; };
const onClosed = () => { const onClosed = () => {

View File

@ -88,7 +88,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="appearNote.files && appearNote.files.length > 0"> <div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/> <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div> </div>
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/> <MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :author="appearNote.user" :emojiUrls="appearNote.emojis" :class="$style.poll"/>
<div v-if="isEnabledUrlPreview"> <div v-if="isEnabledUrlPreview">
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/> <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/>
</div> </div>

View File

@ -109,7 +109,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="appearNote.files && appearNote.files.length > 0"> <div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/> <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div> </div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/> <MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll" :author="appearNote.user" :emojiUrls="appearNote.emojis"/>
<div v-if="isEnabledUrlPreview"> <div v-if="isEnabledUrlPreview">
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/> <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
</div> </div>

View File

@ -0,0 +1,124 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="$style.root">
<MkButton primary :disabled="min === current" @click="onToPrevButtonClicked">&lt;</MkButton>
<div :class="$style.buttons">
<div v-if="prevDotVisible" :class="$style.headTailButtons">
<MkButton @click="onToHeadButtonClicked">{{ min }}</MkButton>
<span class="ti ti-dots"/>
</div>
<MkButton
v-for="i in buttonRanges" :key="i"
:disabled="current === i"
@click="onNumberButtonClicked(i)"
>
{{ i }}
</MkButton>
<div v-if="nextDotVisible" :class="$style.headTailButtons">
<span class="ti ti-dots"/>
<MkButton @click="onToTailButtonClicked">{{ max }}</MkButton>
</div>
</div>
<MkButton primary :disabled="max === current" @click="onToNextButtonClicked">&gt;</MkButton>
</div>
</template>
<script setup lang="ts">
import { computed, toRefs } from 'vue';
import MkButton from '@/components/MkButton.vue';
const min = 1;
const emit = defineEmits<{
(ev: 'pageChanged', pageNumber: number): void;
}>();
const props = defineProps<{
current: number;
max: number;
buttonCount: number;
}>();
const { current, max } = toRefs(props);
const buttonCount = computed(() => Math.min(max.value, props.buttonCount));
const buttonCountHalf = computed(() => Math.floor(buttonCount.value / 2));
const buttonCountStart = computed(() => Math.min(Math.max(min, current.value - buttonCountHalf.value), max.value - buttonCount.value + 1));
const buttonRanges = computed(() => Array.from({ length: buttonCount.value }, (_, i) => buttonCountStart.value + i));
const prevDotVisible = computed(() => (current.value - 1 > buttonCountHalf.value) && (max.value > buttonCount.value));
const nextDotVisible = computed(() => (current.value < max.value - buttonCountHalf.value) && (max.value > buttonCount.value));
if (_DEV_) {
console.log('[MkPagingButtons]', current.value, max.value, buttonCount.value, buttonCountHalf.value);
console.log('[MkPagingButtons]', current.value < max.value - buttonCountHalf.value);
console.log('[MkPagingButtons]', max.value > buttonCount.value);
}
function onNumberButtonClicked(pageNumber: number) {
emit('pageChanged', pageNumber);
}
function onToHeadButtonClicked() {
emit('pageChanged', min);
}
function onToPrevButtonClicked() {
const newPageNumber = current.value <= min ? min : current.value - 1;
emit('pageChanged', newPageNumber);
}
function onToNextButtonClicked() {
const newPageNumber = current.value >= max.value ? max.value : current.value + 1;
emit('pageChanged', newPageNumber);
}
function onToTailButtonClicked() {
emit('pageChanged', max.value);
}
</script>
<style module lang="scss">
.root {
display: flex;
justify-content: center;
align-items: center;
gap: 24px;
button {
border-radius: 9999px;
min-width: 2.5em;
min-height: 2.5em;
max-width: 2.5em;
max-height: 2.5em;
padding: 4px;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.headTailButtons {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
span {
font-size: 0.75em;
}
}
</style>

View File

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.bg" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div> <div :class="$style.bg" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
<span :class="$style.fg"> <span :class="$style.fg">
<template v-if="choice.isVoted"><i class="ti ti-check" style="margin-right: 4px; color: var(--MI_THEME-accent);"></i></template> <template v-if="choice.isVoted"><i class="ti ti-check" style="margin-right: 4px; color: var(--MI_THEME-accent);"></i></template>
<Mfm :text="choice.text" :plain="true"/> <Mfm :text="choice.text" :plain="true" :author="author" :emojiUrls="emojiUrls"/>
<span v-if="showResult" style="margin-left: 4px; opacity: 0.7;">({{ i18n.tsx._poll.votesCount({ n: choice.votes }) }})</span> <span v-if="showResult" style="margin-left: 4px; opacity: 0.7;">({{ i18n.tsx._poll.votesCount({ n: choice.votes }) }})</span>
</span> </span>
</li> </li>
@ -42,6 +42,8 @@ const props = defineProps<{
noteId: string; noteId: string;
poll: NonNullable<Misskey.entities.Note['poll']>; poll: NonNullable<Misskey.entities.Note['poll']>;
readOnly?: boolean; readOnly?: boolean;
emojiUrls?: Record<string, string>;
author?: Misskey.entities.UserLite;
}>(); }>();
const remaining = ref(-1); const remaining = ref(-1);

View File

@ -0,0 +1,106 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import { http, HttpResponse } from 'msw';
import { role } from '../../.storybook/fakes.js';
import { commonHandlers } from '../../.storybook/mocks.js';
import MkRoleSelectDialog from '@/components/MkRoleSelectDialog.vue';
const roles = [
role({ displayOrder: 1 }, '1'), role({ displayOrder: 1 }, '1'), role({ displayOrder: 1 }, '1'), role({ displayOrder: 1 }, '1'),
role({ displayOrder: 2 }, '2'), role({ displayOrder: 2 }, '2'), role({ displayOrder: 3 }, '3'), role({ displayOrder: 3 }, '3'),
role({ displayOrder: 4 }, '4'), role({ displayOrder: 5 }, '5'), role({ displayOrder: 6 }, '6'), role({ displayOrder: 7 }, '7'),
role({ displayOrder: 999, name: 'privateRole', isPublic: false }, '999'),
];
export const Default = {
render(args) {
return {
components: {
MkRoleSelectDialog,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MkRoleSelectDialog v-bind="props" />',
};
},
args: {
initialRoleIds: undefined,
infoMessage: undefined,
title: undefined,
publicOnly: true,
},
parameters: {
layout: 'centered',
msw: {
handlers: [
...commonHandlers,
http.post('/api/admin/roles/list', ({ params }) => {
return HttpResponse.json(roles);
}),
],
},
},
decorators: [() => ({
template: '<div style="width:100cqmin"><story/></div>',
})],
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const InitialIds = {
...Default,
args: {
...Default.args,
initialRoleIds: [roles[0].id, roles[1].id, roles[4].id, roles[6].id, roles[8].id, roles[10].id],
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const InfoMessage = {
...Default,
args: {
...Default.args,
infoMessage: 'This is a message.',
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const Title = {
...Default,
args: {
...Default.args,
title: 'Select roles',
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const Full = {
...Default,
args: {
...Default.args,
initialRoleIds: roles.map(it => it.id),
infoMessage: InfoMessage.args.infoMessage,
title: Title.args.title,
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const FullWithPrivate = {
...Default,
args: {
...Default.args,
initialRoleIds: roles.map(it => it.id),
infoMessage: InfoMessage.args.infoMessage,
title: Title.args.title,
publicOnly: false,
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;

View File

@ -0,0 +1,200 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkModalWindow
ref="windowEl"
:withOkButton="false"
:okButtonDisabled="false"
:width="400"
:height="500"
@close="onCloseModalWindow"
@closed="console.log('MkRoleSelectDialog: closed') ; $emit('dispose')"
>
<template #header>{{ title }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<MkLoading v-if="fetching"/>
<div v-else class="_gaps" :class="$style.root">
<div :class="$style.header">
<MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
</div>
<div v-if="selectedRoles.length > 0" class="_gaps" :class="$style.roleItemArea">
<div v-for="role in selectedRoles" :key="role.id" :class="$style.roleItem">
<MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false" style="pointer-events: none;"/>
<button class="_button" :class="$style.roleUnAssign" @click="removeRole(role.id)"><i class="ti ti-x"></i></button>
</div>
</div>
<div v-else :class="$style.roleItemArea" style="text-align: center">
{{ i18n.ts._roleSelectDialog.notSelected }}
</div>
<MkInfo v-if="infoMessage">{{ infoMessage }}</MkInfo>
<div :class="$style.buttons">
<MkButton primary @click="onOkClicked">{{ i18n.ts.ok }}</MkButton>
<MkButton @click="onCancelClicked">{{ i18n.ts.cancel }}</MkButton>
</div>
</div>
</MkSpacer>
</MkModalWindow>
</template>
<script setup lang="ts">
import { computed, defineProps, ref, toRefs } from 'vue';
import * as Misskey from 'misskey-js';
import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkRolePreview from '@/components/MkRolePreview.vue';
import { misskeyApi } from '@/scripts/misskey-api.js';
import * as os from '@/os.js';
import MkSpacer from '@/components/global/MkSpacer.vue';
import MkModalWindow from '@/components/MkModalWindow.vue';
import MkLoading from '@/components/global/MkLoading.vue';
const emit = defineEmits<{
(ev: 'done', value: Misskey.entities.Role[]),
(ev: 'close'),
(ev: 'dispose'),
}>();
const props = withDefaults(defineProps<{
initialRoleIds?: string[],
infoMessage?: string,
title?: string,
publicOnly: boolean,
}>(), {
initialRoleIds: undefined,
infoMessage: undefined,
title: undefined,
publicOnly: true,
});
const { initialRoleIds, infoMessage, title, publicOnly } = toRefs(props);
const windowEl = ref<InstanceType<typeof MkModalWindow>>();
const roles = ref<Misskey.entities.Role[]>([]);
const selectedRoleIds = ref<string[]>(initialRoleIds.value ?? []);
const fetching = ref(false);
const selectedRoles = computed(() => {
const r = roles.value.filter(role => selectedRoleIds.value.includes(role.id));
r.sort((a, b) => {
if (a.displayOrder !== b.displayOrder) {
return b.displayOrder - a.displayOrder;
}
return a.id.localeCompare(b.id);
});
return r;
});
async function fetchRoles() {
fetching.value = true;
const result = await misskeyApi('admin/roles/list', {});
roles.value = result.filter(it => publicOnly.value ? it.isPublic : true);
fetching.value = false;
}
async function addRole() {
const items = roles.value
.filter(r => r.isPublic)
.filter(r => !selectedRoleIds.value.includes(r.id))
.map(r => ({ text: r.name, value: r }));
const { canceled, result: role } = await os.select({ items });
if (canceled) {
return;
}
selectedRoleIds.value.push(role.id);
}
async function removeRole(roleId: string) {
selectedRoleIds.value = selectedRoleIds.value.filter(x => x !== roleId);
}
function onOkClicked() {
emit('done', selectedRoles.value);
windowEl.value?.close();
}
function onCancelClicked() {
emit('close');
windowEl.value?.close();
}
function onCloseModalWindow() {
emit('close');
windowEl.value?.close();
}
fetchRoles();
</script>
<style module lang="scss">
.root {
max-height: 410px;
height: 410px;
display: flex;
flex-direction: column;
}
.roleItemArea {
background-color: var(--MI_THEME-acrylicBg);
border-radius: var(--MI-radius);
padding: 12px;
overflow-y: auto;
}
.roleItem {
display: flex;
}
.role {
flex: 1;
}
.roleUnAssign {
width: 32px;
height: 32px;
margin-left: 8px;
align-self: center;
}
.header {
display: flex;
align-items: center;
justify-content: flex-start;
}
.title {
flex: 1;
}
.addRoleButton {
min-width: 32px;
min-height: 32px;
max-width: 32px;
max-height: 32px;
margin-left: 8px;
align-self: center;
padding: 0;
}
.buttons {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
margin-top: auto;
}
.divider {
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View File

@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export type SortOrderDirection = '+' | '-'
export type SortOrder<T extends string> = {
key: T;
direction: SortOrderDirection;
}

View File

@ -0,0 +1,112 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="$style.sortOrderArea">
<div :class="$style.sortOrderAreaTags">
<MkTagItem
v-for="order in currentOrders"
:key="order.key"
:iconClass="order.direction === '+' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
:exButtonIconClass="'ti ti-x'"
:content="order.key"
@click="onToggleSortOrderButtonClicked(order)"
@exButtonClick="onRemoveSortOrderButtonClicked(order)"
/>
</div>
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
<span class="ti ti-plus"/>
</MkButton>
</div>
</template>
<script setup lang="ts" generic="T extends string">
import { toRefs } from 'vue';
import MkTagItem from '@/components/MkTagItem.vue';
import MkButton from '@/components/MkButton.vue';
import { MenuItem } from '@/types/menu.js';
import * as os from '@/os.js';
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
const emit = defineEmits<{
(ev: 'update', sortOrders: SortOrder<T>[]): void;
}>();
const props = defineProps<{
baseOrderKeyNames: T[];
currentOrders: SortOrder<T>[];
}>();
const { currentOrders } = toRefs(props);
function onToggleSortOrderButtonClicked(order: SortOrder<T>) {
switch (order.direction) {
case '+':
order.direction = '-';
break;
case '-':
order.direction = '+';
break;
}
emitOrder(currentOrders.value);
}
function onAddSortOrderButtonClicked(ev: MouseEvent) {
const menuItems: MenuItem[] = props.baseOrderKeyNames
.filter(baseKey => !currentOrders.value.map(it => it.key).includes(baseKey))
.map(it => {
return {
text: it,
action: () => {
emitOrder([...currentOrders.value, { key: it, direction: '+' }]);
},
};
});
os.contextMenu(menuItems, ev);
}
function onRemoveSortOrderButtonClicked(order: SortOrder<T>) {
emitOrder(currentOrders.value.filter(it => it.key !== order.key));
}
function emitOrder(sortOrders: SortOrder<T>[]) {
emit('update', sortOrders);
}
</script>
<style module lang="scss">
.sortOrderArea {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
}
.sortOrderAreaTags {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
flex-wrap: wrap;
gap: 8px;
}
.sortOrderAddButton {
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
min-width: 2.0em;
min-height: 2.0em;
max-width: 2.0em;
max-height: 2.0em;
padding: 8px;
margin-left: auto;
border-radius: 9999px;
background-color: var(--MI_THEME-buttonBg);
}
</style>

View File

@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</details> </details>
<details v-if="note.poll"> <details v-if="note.poll">
<summary>{{ i18n.ts.poll }}</summary> <summary>{{ i18n.ts.poll }}</summary>
<MkPoll :noteId="note.id" :poll="note.poll"/> <MkPoll :noteId="note.id" :poll="note.poll" :author="note.user" :emojiUrls="note.emojis"/>
</details> </details>
<button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click="collapsed = false"> <button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click="collapsed = false">
<span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span> <span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span>
@ -32,10 +32,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { shouldCollapsed } from '@@/js/collapsed.js';
import MkMediaList from '@/components/MkMediaList.vue'; import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue'; import MkPoll from '@/components/MkPoll.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { shouldCollapsed } from '@@/js/collapsed.js';
const props = defineProps<{ const props = defineProps<{
note: Misskey.entities.Note; note: Misskey.entities.Note;

View File

@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable import/no-default-export */
import { action } from '@storybook/addon-actions';
import { StoryObj } from '@storybook/vue3';
import MkTagItem from './MkTagItem.vue';
export const Default = {
render(args) {
return {
components: {
MkTagItem: MkTagItem,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
events() {
return {
click: action('click'),
exButtonClick: action('exButtonClick'),
};
},
},
template: '<MkTagItem v-bind="props" v-on="events"></MkTagItem>',
};
},
args: {
content: 'name',
},
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MkTagItem>;
export const Icon = {
...Default,
args: {
...Default.args,
iconClass: 'ti ti-arrow-up',
},
} satisfies StoryObj<typeof MkTagItem>;
export const ExButton = {
...Default,
args: {
...Default.args,
exButtonIconClass: 'ti ti-x',
},
} satisfies StoryObj<typeof MkTagItem>;
export const IconExButton = {
...Default,
args: {
...Default.args,
iconClass: 'ti ti-arrow-up',
exButtonIconClass: 'ti ti-x',
},
} satisfies StoryObj<typeof MkTagItem>;

View File

@ -0,0 +1,76 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="$style.root" @click="(ev) => emit('click', ev)">
<span v-if="iconClass" :class="[$style.icon, iconClass]"/>
<span :class="$style.content">{{ content }}</span>
<MkButton v-if="exButtonIconClass" :class="$style.exButton" @click="(ev) => emit('exButtonClick', ev)">
<span :class="[$style.exButtonIcon, exButtonIconClass]"/>
</MkButton>
</div>
</template>
<script setup lang="ts">
import MkButton from '@/components/MkButton.vue';
const emit = defineEmits<{
(ev: 'click', payload: MouseEvent): void;
(ev: 'exButtonClick', payload: MouseEvent): void;
}>();
defineProps<{
iconClass?: string;
content: string;
exButtonIconClass?: string
}>();
</script>
<style module lang="scss">
$buttonSize : 1.8em;
.root {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 9999px;
padding: 4px 6px;
gap: 3px;
background-color: var(--MI_THEME-buttonBg);
&:hover {
background-color: var(--MI_THEME-buttonHoverBg);
}
}
.icon {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 0.70em;
}
.exButton {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 9999px;
max-height: $buttonSize;
max-width: $buttonSize;
min-height: $buttonSize;
min-width: $buttonSize;
padding: 0;
box-sizing: border-box;
font-size: 0.65em;
}
.exButtonIcon {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 0.80em;
}
</style>

View File

@ -132,6 +132,7 @@ function showMenu(ev: MouseEvent) {
height: 32px; height: 32px;
border-radius: 8px; border-radius: 8px;
font-size: 18px; font-size: 18px;
z-index: 50;
} }
.mainFg { .mainFg {

View File

@ -0,0 +1,35 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkTooltip ref="tooltip" :showing="showing" :targetElement="targetElement" :maxWidth="250" @closed="emit('closed')">
<div :class="$style.root">
{{ content }}
</div>
</MkTooltip>
</template>
<script lang="ts" setup>
import { } from 'vue';
import MkTooltip from '@/components/MkTooltip.vue';
defineProps<{
showing: boolean;
content: string;
targetElement: HTMLElement;
}>();
const emit = defineEmits<{
(ev: 'closed'): void;
}>();
</script>
<style lang="scss" module>
.root {
font-size: 0.9em;
text-align: left;
text-wrap: normal;
}
</style>

View File

@ -0,0 +1,391 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
v-if="cell.row.using"
ref="rootEl"
class="mk_grid_td"
:class="$style.cell"
:style="{ maxWidth: cellWidth, minWidth: cellWidth }"
:tabindex="-1"
data-grid-cell
:data-grid-cell-row="cell.row.index"
:data-grid-cell-col="cell.column.index"
@keydown="onCellKeyDown"
@dblclick.prevent="onCellDoubleClick"
>
<div
:class="[
$style.root,
[(cell.violation.valid || cell.selected) ? {} : $style.error],
[cell.selected ? $style.selected : {}],
//
[(cell.ranged && !cell.row.ranged) ? $style.ranged : {}],
[needsContentCentering ? $style.center : {}],
]"
>
<div v-if="!editing" :class="[$style.contentArea]" :style="cellType === 'boolean' ? 'justify-content: center' : ''">
<div ref="contentAreaEl" :class="$style.content">
<div v-if="cellType === 'text'">
{{ cell.value }}
</div>
<div v-if="cellType === 'number'">
{{ cell.value }}
</div>
<div v-if="cellType === 'date'">
{{ cell.value }}
</div>
<div v-else-if="cellType === 'boolean'">
<span v-if="cell.value === true" class="ti ti-check"/>
<span v-else class="ti"/>
</div>
<div v-else-if="cellType === 'image'">
<img
:src="cell.value as string"
:alt="cell.value as string"
:class="$style.viewImage"
@load="emitContentSizeChanged"
/>
</div>
</div>
</div>
<div v-else ref="inputAreaEl" :class="$style.inputArea">
<input
v-if="cellType === 'text'"
type="text"
:class="$style.editingInput"
:value="editingValue"
@input="onInputText"
@mousedown.stop
@contextmenu.stop
/>
<input
v-if="cellType === 'number'"
type="number"
:class="$style.editingInput"
:value="editingValue"
@input="onInputText"
@mousedown.stop
@contextmenu.stop
/>
<input
v-if="cellType === 'date'"
type="date"
:class="$style.editingInput"
:value="editingValue"
@input="onInputText"
@mousedown.stop
@contextmenu.stop
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, defineAsyncComponent, nextTick, onMounted, onUnmounted, ref, shallowRef, toRefs, watch } from 'vue';
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
import { useTooltip } from '@/scripts/use-tooltip.js';
import * as os from '@/os.js';
import { CellValue, GridCell } from '@/components/grid/cell.js';
import { equalCellAddress, getCellAddress } from '@/components/grid/grid-utils.js';
import { GridRowSetting } from '@/components/grid/row.js';
const emit = defineEmits<{
(ev: 'operation:beginEdit', sender: GridCell): void;
(ev: 'operation:endEdit', sender: GridCell): void;
(ev: 'change:value', sender: GridCell, newValue: CellValue): void;
(ev: 'change:contentSize', sender: GridCell, newSize: Size): void;
}>();
const props = defineProps<{
cell: GridCell,
rowSetting: GridRowSetting,
bus: GridEventEmitter,
}>();
const { cell, bus } = toRefs(props);
const rootEl = shallowRef<InstanceType<typeof HTMLTableCellElement>>();
const contentAreaEl = shallowRef<InstanceType<typeof HTMLDivElement>>();
const inputAreaEl = shallowRef<InstanceType<typeof HTMLDivElement>>();
/** 値が編集中かどうか */
const editing = ref<boolean>(false);
/** 編集中の値. {@link beginEditing}と{@link endEditing}内、および各inputタグやそのコールバックからの操作のみを想定する */
const editingValue = ref<CellValue>(undefined);
const cellWidth = computed(() => cell.value.column.width);
const cellType = computed(() => cell.value.column.setting.type);
const needsContentCentering = computed(() => {
switch (cellType.value) {
case 'boolean':
return true;
default:
return false;
}
});
watch(() => [cell.value.value], () => {
//
nextTick(emitContentSizeChanged);
}, { immediate: true });
watch(() => cell.value.selected, () => {
if (cell.value.selected) {
requestFocus();
}
});
function onCellDoubleClick(ev: MouseEvent) {
switch (ev.type) {
case 'dblclick': {
beginEditing(ev.target as HTMLElement);
break;
}
}
}
function onOutsideMouseDown(ev: MouseEvent) {
const isOutside = ev.target instanceof Node && !rootEl.value?.contains(ev.target);
if (isOutside || !equalCellAddress(cell.value.address, getCellAddress(ev.target as HTMLElement))) {
endEditing(true, false);
}
}
function onCellKeyDown(ev: KeyboardEvent) {
if (!editing.value) {
ev.preventDefault();
switch (ev.code) {
case 'NumpadEnter':
case 'Enter':
case 'F2': {
beginEditing(ev.target as HTMLElement);
break;
}
}
} else {
switch (ev.code) {
case 'Escape': {
endEditing(false, true);
break;
}
case 'NumpadEnter':
case 'Enter': {
if (!ev.isComposing) {
endEditing(true, true);
}
}
}
}
}
function onInputText(ev: Event) {
editingValue.value = (ev.target as HTMLInputElement).value;
}
function onForceRefreshContentSize() {
emitContentSizeChanged();
}
function registerOutsideMouseDown() {
unregisterOutsideMouseDown();
addEventListener('mousedown', onOutsideMouseDown);
}
function unregisterOutsideMouseDown() {
removeEventListener('mousedown', onOutsideMouseDown);
}
async function beginEditing(target: HTMLElement) {
if (editing.value || !cell.value.selected || !cell.value.column.setting.editable) {
return;
}
if (cell.value.column.setting.customValueEditor) {
emit('operation:beginEdit', cell.value);
const newValue = await cell.value.column.setting.customValueEditor(
cell.value.row,
cell.value.column,
cell.value.value,
target,
);
emit('operation:endEdit', cell.value);
if (newValue !== cell.value.value) {
emitValueChange(newValue);
}
requestFocus();
} else {
switch (cellType.value) {
case 'number':
case 'date':
case 'text': {
editingValue.value = cell.value.value;
editing.value = true;
registerOutsideMouseDown();
emit('operation:beginEdit', cell.value);
await nextTick(() => {
// input
if (inputAreaEl.value) {
(inputAreaEl.value.querySelector('*') as HTMLElement).focus();
}
});
break;
}
case 'boolean': {
// UI
emitValueChange(!cell.value.value);
break;
}
}
}
}
function endEditing(applyValue: boolean, requireFocus: boolean) {
if (!editing.value) {
return;
}
const newValue = editingValue.value;
editingValue.value = undefined;
emit('operation:endEdit', cell.value);
unregisterOutsideMouseDown();
if (applyValue && newValue !== cell.value.value) {
emitValueChange(newValue);
}
editing.value = false;
if (requireFocus) {
requestFocus();
}
}
function requestFocus() {
nextTick(() => {
rootEl.value?.focus();
});
}
function emitValueChange(newValue: CellValue) {
const _cell = cell.value;
emit('change:value', _cell, newValue);
}
function emitContentSizeChanged() {
emit('change:contentSize', cell.value, {
width: contentAreaEl.value?.clientWidth ?? 0,
height: contentAreaEl.value?.clientHeight ?? 0,
});
}
useTooltip(rootEl, (showing) => {
if (cell.value.violation.valid) {
return;
}
const content = cell.value.violation.violations.filter(it => !it.valid).map(it => it.result.message).join('\n');
const result = os.popup(defineAsyncComponent(() => import('@/components/grid/MkCellTooltip.vue')), {
showing,
content,
targetElement: rootEl.value!,
}, {
closed: () => {
result.dispose();
},
});
});
onMounted(() => {
bus.value.on('forceRefreshContentSize', onForceRefreshContentSize);
});
onUnmounted(() => {
bus.value.off('forceRefreshContentSize', onForceRefreshContentSize);
});
</script>
<style module lang="scss">
$cellHeight: 28px;
.cell {
overflow: hidden;
white-space: nowrap;
height: $cellHeight;
max-height: $cellHeight;
min-height: $cellHeight;
cursor: cell;
&:focus {
outline: none;
}
}
.root {
display: flex;
flex-direction: row;
align-items: center;
box-sizing: border-box;
height: 100%;
// selected
border: solid 0.5px transparent;
&.selected {
border: solid 0.5px var(--MI_THEME-accentLighten);
}
&.ranged {
background-color: var(--MI_THEME-accentedBg);
}
&.center {
justify-content: center;
}
&.error {
border: solid 0.5px var(--MI_THEME-error);
}
}
.contentArea, .inputArea {
display: flex;
align-items: center;
width: 100%;
max-width: 100%;
}
.content {
display: inline-block;
padding: 0 8px;
}
.viewImage {
width: auto;
max-height: $cellHeight;
height: $cellHeight;
object-fit: cover;
}
.editingInput {
padding: 0 8px;
width: 100%;
max-width: 100%;
box-sizing: border-box;
min-height: $cellHeight - 2;
max-height: $cellHeight - 2;
height: $cellHeight - 2;
outline: none;
border: none;
font-family: 'Hiragino Maru Gothic Pro', "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif;
}
</style>

View File

@ -0,0 +1,72 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
class="mk_grid_tr"
:class="[
$style.row,
row.ranged ? $style.ranged : {},
...(row.additionalStyles ?? []).map(it => it.className ?? {}),
]"
:style="[
...(row.additionalStyles ?? []).map(it => it.style ?? {}),
]"
:data-grid-row="row.index"
>
<MkNumberCell
v-if="setting.showNumber"
:content="(row.index + 1).toString()"
:row="row"
/>
<MkDataCell
v-for="cell in cells"
:key="cell.address.col"
:vIf="cell.column.setting.type !== 'hidden'"
:cell="cell"
:rowSetting="setting"
:bus="bus"
@operation:beginEdit="(sender) => emit('operation:beginEdit', sender)"
@operation:endEdit="(sender) => emit('operation:endEdit', sender)"
@change:value="(sender, newValue) => emit('change:value', sender, newValue)"
@change:contentSize="(sender, newSize) => emit('change:contentSize', sender, newSize)"
/>
</div>
</template>
<script setup lang="ts">
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
import MkDataCell from '@/components/grid/MkDataCell.vue';
import MkNumberCell from '@/components/grid/MkNumberCell.vue';
import { CellValue, GridCell } from '@/components/grid/cell.js';
import { GridRow, GridRowSetting } from '@/components/grid/row.js';
const emit = defineEmits<{
(ev: 'operation:beginEdit', sender: GridCell): void;
(ev: 'operation:endEdit', sender: GridCell): void;
(ev: 'change:value', sender: GridCell, newValue: CellValue): void;
(ev: 'change:contentSize', sender: GridCell, newSize: Size): void;
}>();
defineProps<{
row: GridRow,
cells: GridCell[],
setting: GridRowSetting,
bus: GridEventEmitter,
}>();
</script>
<style module lang="scss">
.row {
display: flex;
flex-direction: row;
align-items: center;
width: fit-content;
&.ranged {
background-color: var(--MI_THEME-accentedBg);
}
}
</style>

View File

@ -0,0 +1,223 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { action } from '@storybook/addon-actions';
import { StoryObj } from '@storybook/vue3';
import { ref } from 'vue';
import { commonHandlers } from '../../../.storybook/mocks.js';
import { boolean, choose, country, date, firstName, integer, lastName, text } from '../../../.storybook/fake-utils.js';
import MkGrid from './MkGrid.vue';
import { GridContext, GridEvent } from '@/components/grid/grid-event.js';
import { DataSource, GridSetting } from '@/components/grid/grid.js';
import { GridColumnSetting } from '@/components/grid/column.js';
function d(p: {
check?: boolean,
name?: string,
email?: string,
age?: number,
birthday?: string,
gender?: string,
country?: string,
reportCount?: number,
createdAt?: string,
}, seed: string) {
const prefix = text(10, seed);
return {
check: p.check ?? boolean(seed),
name: p.name ?? `${firstName(seed)} ${lastName(seed)}`,
email: p.email ?? `${prefix}@example.com`,
age: p.age ?? integer(20, 80, seed),
birthday: date({}, seed).toISOString(),
gender: p.gender ?? choose(['male', 'female', 'other', 'unknown'], seed),
country: p.country ?? country(seed),
reportCount: p.reportCount ?? integer(0, 9999, seed),
createdAt: p.createdAt ?? date({}, seed).toISOString(),
};
}
const defaultCols: GridColumnSetting[] = [
{ bindTo: 'check', icon: 'ti-check', type: 'boolean', width: 50 },
{ bindTo: 'name', title: 'Name', type: 'text', width: 'auto' },
{ bindTo: 'email', title: 'Email', type: 'text', width: 'auto' },
{ bindTo: 'age', title: 'Age', type: 'number', width: 50 },
{ bindTo: 'birthday', title: 'Birthday', type: 'date', width: 'auto' },
{ bindTo: 'gender', title: 'Gender', type: 'text', width: 80 },
{ bindTo: 'country', title: 'Country', type: 'text', width: 120 },
{ bindTo: 'reportCount', title: 'ReportCount', type: 'number', width: 'auto' },
{ bindTo: 'createdAt', title: 'CreatedAt', type: 'date', width: 'auto' },
];
function createArgs(overrides?: { settings?: Partial<GridSetting>, data?: DataSource[] }) {
const refData = ref<ReturnType<typeof d>[]>([]);
for (let i = 0; i < 100; i++) {
refData.value.push(d({}, i.toString()));
}
return {
settings: {
row: overrides?.settings?.row,
cols: [
...defaultCols.filter(col => overrides?.settings?.cols?.every(c => c.bindTo !== col.bindTo) ?? true),
...overrides?.settings?.cols ?? [],
],
cells: overrides?.settings?.cells,
},
data: refData.value,
};
}
function createRender(params: { settings: GridSetting, data: DataSource[] }) {
return {
render(args) {
return {
components: {
MkGrid,
},
setup() {
return {
args,
};
},
data() {
return {
data: args.data,
};
},
computed: {
props() {
return {
...args,
};
},
events() {
return {
event: (event: GridEvent, context: GridContext) => {
switch (event.type) {
case 'cell-value-change': {
args.data[event.row.index][event.column.setting.bindTo] = event.newValue;
}
}
},
};
},
},
template: '<div style="padding:20px"><MkGrid v-bind="props" v-on="events" /></div>',
};
},
args: {
...params,
},
parameters: {
layout: 'fullscreen',
msw: {
handlers: [
...commonHandlers,
],
},
},
} satisfies StoryObj<typeof MkGrid>;
}
export const Default = createRender(createArgs());
export const NoNumber = createRender(createArgs({
settings: {
row: {
showNumber: false,
},
},
}));
export const NoSelectable = createRender(createArgs({
settings: {
row: {
selectable: false,
},
},
}));
export const Editable = createRender(createArgs({
settings: {
cols: defaultCols.map(col => ({ ...col, editable: true })),
},
}));
export const AdditionalRowStyle = createRender(createArgs({
settings: {
cols: defaultCols.map(col => ({ ...col, editable: true })),
row: {
styleRules: [
{
condition: ({ row }) => AdditionalRowStyle.args.data[row.index].check as boolean,
applyStyle: {
style: {
backgroundColor: 'lightgray',
},
},
},
],
},
},
}));
export const ContextMenu = createRender(createArgs({
settings: {
cols: [
{
bindTo: 'check', icon: 'ti-check', type: 'boolean', width: 50, contextMenuFactory: (col, context) => [
{
type: 'button',
text: 'Check All',
action: () => {
for (const d of ContextMenu.args.data) {
d.check = true;
}
},
},
{
type: 'button',
text: 'Uncheck All',
action: () => {
for (const d of ContextMenu.args.data) {
d.check = false;
}
},
},
],
},
],
row: {
contextMenuFactory: (row, context) => [
{
type: 'button',
text: 'Delete',
action: () => {
const idxes = context.rangedRows.map(r => r.index);
const newData = ContextMenu.args.data.filter((d, i) => !idxes.includes(i));
ContextMenu.args.data.splice(0);
ContextMenu.args.data.push(...newData);
},
},
],
},
cells: {
contextMenuFactory: (col, row, value, context) => [
{
type: 'button',
text: 'Delete',
action: () => {
for (const cell of context.rangedCells) {
ContextMenu.args.data[cell.row.index][cell.column.setting.bindTo] = undefined;
}
},
},
],
},
},
}));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
ref="rootEl"
class="mk_grid_th"
:class="$style.cell"
:style="[{ maxWidth: column.width, minWidth: column.width, width: column.width }]"
data-grid-cell
:data-grid-cell-row="-1"
:data-grid-cell-col="column.index"
>
<div :class="$style.root">
<div :class="$style.left"/>
<div :class="$style.wrapper">
<div ref="contentEl" :class="$style.contentArea">
<span v-if="column.setting.icon" class="ti" :class="column.setting.icon" style="line-height: normal"/>
<span v-else>{{ text }}</span>
</div>
</div>
<div
:class="$style.right"
@mousedown="onHandleMouseDown"
@dblclick="onHandleDoubleClick"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
import { GridColumn } from '@/components/grid/column.js';
const emit = defineEmits<{
(ev: 'operation:beginWidthChange', sender: GridColumn): void;
(ev: 'operation:endWidthChange', sender: GridColumn): void;
(ev: 'operation:widthLargest', sender: GridColumn): void;
(ev: 'change:width', sender: GridColumn, width: string): void;
(ev: 'change:contentSize', sender: GridColumn, newSize: Size): void;
}>();
const props = defineProps<{
column: GridColumn,
bus: GridEventEmitter,
}>();
const { column, bus } = toRefs(props);
const rootEl = ref<InstanceType<typeof HTMLTableCellElement>>();
const contentEl = ref<InstanceType<typeof HTMLDivElement>>();
const resizing = ref<boolean>(false);
const text = computed(() => {
const result = column.value.setting.title ?? column.value.setting.bindTo;
return result.length > 0 ? result : ' ';
});
watch(column, () => {
//
nextTick(emitContentSizeChanged);
}, { immediate: true });
function onHandleDoubleClick(ev: MouseEvent) {
switch (ev.type) {
case 'dblclick': {
emit('operation:widthLargest', column.value);
break;
}
}
}
function onHandleMouseDown(ev: MouseEvent) {
switch (ev.type) {
case 'mousedown': {
if (!resizing.value) {
registerHandleMouseUp();
registerHandleMouseMove();
resizing.value = true;
emit('operation:beginWidthChange', column.value);
}
break;
}
}
}
function onHandleMouseMove(ev: MouseEvent) {
if (!rootEl.value) {
//
return;
}
switch (ev.type) {
case 'mousemove': {
if (resizing.value) {
const bounds = rootEl.value.getBoundingClientRect();
const clientWidth = rootEl.value.clientWidth;
const clientRight = bounds.left + clientWidth;
const nextWidth = clientWidth + (ev.clientX - clientRight);
emit('change:width', column.value, `${nextWidth}px`);
}
break;
}
}
}
function onHandleMouseUp(ev: MouseEvent) {
switch (ev.type) {
case 'mouseup': {
if (resizing.value) {
unregisterHandleMouseUp();
unregisterHandleMouseMove();
resizing.value = false;
emit('operation:endWidthChange', column.value);
}
break;
}
}
}
function onForceRefreshContentSize() {
emitContentSizeChanged();
}
function registerHandleMouseMove() {
unregisterHandleMouseMove();
addEventListener('mousemove', onHandleMouseMove);
}
function unregisterHandleMouseMove() {
removeEventListener('mousemove', onHandleMouseMove);
}
function registerHandleMouseUp() {
unregisterHandleMouseUp();
addEventListener('mouseup', onHandleMouseUp);
}
function unregisterHandleMouseUp() {
removeEventListener('mouseup', onHandleMouseUp);
}
function emitContentSizeChanged() {
const clientWidth = contentEl.value?.clientWidth ?? 0;
const clientHeight = contentEl.value?.clientHeight ?? 0;
emit('change:contentSize', column.value, {
// +3px
width: clientWidth + 3 + 3,
height: clientHeight,
});
}
onMounted(() => {
bus.value.on('forceRefreshContentSize', onForceRefreshContentSize);
});
onUnmounted(() => {
bus.value.off('forceRefreshContentSize', onForceRefreshContentSize);
});
</script>
<style module lang="scss">
$handleWidth: 5px;
$cellHeight: 28px;
.cell {
cursor: pointer;
}
.root {
display: flex;
flex-direction: row;
height: $cellHeight;
max-height: $cellHeight;
min-height: $cellHeight;
.wrapper {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
justify-content: center;
}
.contentArea {
display: flex;
padding: 6px 4px;
box-sizing: border-box;
overflow: hidden;
white-space: nowrap;
text-align: center;
}
.left {
// right
margin-left: -$handleWidth;
margin-right: auto;
width: $handleWidth;
min-width: $handleWidth;
}
.right {
margin-left: auto;
// 使
margin-right: -$handleWidth;
width: $handleWidth;
min-width: $handleWidth;
cursor: w-resize;
z-index: 1;
}
}
</style>

View File

@ -0,0 +1,60 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
class="mk_grid_tr"
:class="$style.root"
:data-grid-row="-1"
>
<MkNumberCell
v-if="gridSetting.showNumber"
content="#"
:top="true"
/>
<MkHeaderCell
v-for="column in columns"
:key="column.index"
:column="column"
:bus="bus"
@operation:beginWidthChange="(sender) => emit('operation:beginWidthChange', sender)"
@operation:endWidthChange="(sender) => emit('operation:endWidthChange', sender)"
@operation:widthLargest="(sender) => emit('operation:widthLargest', sender)"
@change:width="(sender, width) => emit('change:width', sender, width)"
@change:contentSize="(sender, newSize) => emit('change:contentSize', sender, newSize)"
/>
</div>
</template>
<script setup lang="ts">
import { GridEventEmitter, Size } from '@/components/grid/grid.js';
import MkHeaderCell from '@/components/grid/MkHeaderCell.vue';
import MkNumberCell from '@/components/grid/MkNumberCell.vue';
import { GridColumn } from '@/components/grid/column.js';
import { GridRowSetting } from '@/components/grid/row.js';
const emit = defineEmits<{
(ev: 'operation:beginWidthChange', sender: GridColumn): void;
(ev: 'operation:endWidthChange', sender: GridColumn): void;
(ev: 'operation:widthLargest', sender: GridColumn): void;
(ev: 'operation:selectionColumn', sender: GridColumn): void;
(ev: 'change:width', sender: GridColumn, width: string): void;
(ev: 'change:contentSize', sender: GridColumn, newSize: Size): void;
}>();
defineProps<{
columns: GridColumn[],
gridSetting: GridRowSetting,
bus: GridEventEmitter,
}>();
</script>
<style module lang="scss">
.root {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@ -0,0 +1,61 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div
class="mk_grid_th"
:class="[$style.cell]"
:tabindex="-1"
data-grid-cell
:data-grid-cell-row="row?.index ?? -1"
:data-grid-cell-col="-1"
>
<div :class="[$style.root]">
{{ content }}
</div>
</div>
</template>
<script setup lang="ts">
import { GridRow } from '@/components/grid/row.js';
defineProps<{
content: string,
row?: GridRow,
}>();
</script>
<style module lang="scss">
$cellHeight: 28px;
$cellWidth: 34px;
.cell {
overflow: hidden;
white-space: nowrap;
height: $cellHeight;
max-height: $cellHeight;
min-height: $cellHeight;
min-width: $cellWidth;
width: $cellWidth;
cursor: pointer;
}
.root {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: 0 8px;
height: 100%;
border: solid 0.5px transparent;
&.selected {
background-color: var(--MI_THEME-accentedBg);
}
}
</style>

View File

@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { CellValue, GridCell } from '@/components/grid/cell.js';
import { GridColumn } from '@/components/grid/column.js';
import { GridRow } from '@/components/grid/row.js';
import { i18n } from '@/i18n.js';
export type ValidatorParams = {
column: GridColumn;
row: GridRow;
value: CellValue;
allCells: GridCell[];
};
export type ValidatorResult = {
valid: boolean;
message?: string;
}
export type GridCellValidator = {
name?: string;
ignoreViolation?: boolean;
validate: (params: ValidatorParams) => ValidatorResult;
}
export type ValidateViolation = {
valid: boolean;
params: ValidatorParams;
violations: ValidateViolationItem[];
}
export type ValidateViolationItem = {
valid: boolean;
validator: GridCellValidator;
result: ValidatorResult;
}
export function cellValidation(allCells: GridCell[], cell: GridCell, newValue: CellValue): ValidateViolation {
const { column, row } = cell;
const validators = column.setting.validators ?? [];
const params: ValidatorParams = {
column,
row,
value: newValue,
allCells,
};
const violations: ValidateViolationItem[] = validators.map(validator => {
const result = validator.validate(params);
return {
valid: result.valid,
validator,
result,
};
});
return {
valid: violations.every(v => v.result.valid),
params,
violations,
};
}
class ValidatorPreset {
required(): GridCellValidator {
return {
name: 'required',
validate: ({ value }): ValidatorResult => {
return {
valid: value !== null && value !== undefined && value !== '',
message: i18n.ts._gridComponent._error.requiredValue,
};
},
};
}
regex(pattern: RegExp): GridCellValidator {
return {
name: 'regex',
validate: ({ value }): ValidatorResult => {
return {
valid: (typeof value !== 'string') || pattern.test(value.toString() ?? ''),
message: i18n.tsx._gridComponent._error.patternNotMatch({ pattern: pattern.source }),
};
},
};
}
unique(): GridCellValidator {
return {
name: 'unique',
validate: ({ column, row, value, allCells }): ValidatorResult => {
const bindTo = column.setting.bindTo;
const isUnique = allCells
.filter(it => it.column.setting.bindTo === bindTo && it.row.index !== row.index)
.every(cell => cell.value !== value);
return {
valid: isUnique,
message: i18n.ts._gridComponent._error.notUnique,
};
},
};
}
}
export const validators = new ValidatorPreset();

View File

@ -0,0 +1,88 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { ValidateViolation } from '@/components/grid/cell-validators.js';
import { Size } from '@/components/grid/grid.js';
import { GridColumn } from '@/components/grid/column.js';
import { GridRow } from '@/components/grid/row.js';
import { MenuItem } from '@/types/menu.js';
import { GridContext } from '@/components/grid/grid-event.js';
export type CellValue = string | boolean | number | undefined | null | Array<unknown> | NonNullable<unknown>;
export type CellAddress = {
row: number;
col: number;
}
export const CELL_ADDRESS_NONE: CellAddress = {
row: -1,
col: -1,
};
export type GridCell = {
address: CellAddress;
value: CellValue;
column: GridColumn;
row: GridRow;
selected: boolean;
ranged: boolean;
contentSize: Size;
setting: GridCellSetting;
violation: ValidateViolation;
}
export type GridCellContextMenuFactory = (col: GridColumn, row: GridRow, value: CellValue, context: GridContext) => MenuItem[];
export type GridCellSetting = {
contextMenuFactory?: GridCellContextMenuFactory;
}
export function createCell(
column: GridColumn,
row: GridRow,
value: CellValue,
setting: GridCellSetting,
): GridCell {
const newValue = (row.using && column.setting.valueTransformer)
? column.setting.valueTransformer(row, column, value)
: value;
return {
address: { row: row.index, col: column.index },
value: newValue,
column,
row,
selected: false,
ranged: false,
contentSize: { width: 0, height: 0 },
violation: {
valid: true,
params: {
column,
row,
value,
allCells: [],
},
violations: [],
},
setting,
};
}
export function resetCell(cell: GridCell): void {
cell.selected = false;
cell.ranged = false;
cell.violation = {
valid: true,
params: {
column: cell.column,
row: cell.row,
value: cell.value,
allCells: [],
},
violations: [],
};
}

View File

@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { GridCellValidator } from '@/components/grid/cell-validators.js';
import { Size, SizeStyle } from '@/components/grid/grid.js';
import { calcCellWidth } from '@/components/grid/grid-utils.js';
import { CellValue, GridCell } from '@/components/grid/cell.js';
import { GridRow } from '@/components/grid/row.js';
import { MenuItem } from '@/types/menu.js';
import { GridContext } from '@/components/grid/grid-event.js';
export type ColumnType = 'text' | 'number' | 'date' | 'boolean' | 'image' | 'hidden';
export type CustomValueEditor = (row: GridRow, col: GridColumn, value: CellValue, cellElement: HTMLElement) => Promise<CellValue>;
export type CellValueTransformer = (row: GridRow, col: GridColumn, value: CellValue) => CellValue;
export type GridColumnContextMenuFactory = (col: GridColumn, context: GridContext) => MenuItem[];
export type GridColumnSetting = {
bindTo: string;
title?: string;
icon?: string;
type: ColumnType;
width: SizeStyle;
editable?: boolean;
validators?: GridCellValidator[];
customValueEditor?: CustomValueEditor;
valueTransformer?: CellValueTransformer;
contextMenuFactory?: GridColumnContextMenuFactory;
events?: {
copy?: (value: CellValue) => string;
paste?: (text: string) => CellValue;
delete?: (cell: GridCell, context: GridContext) => void;
}
};
export type GridColumn = {
index: number;
setting: GridColumnSetting;
width: string;
contentSize: Size;
}
export function createColumn(setting: GridColumnSetting, index: number): GridColumn {
return {
index,
setting,
width: calcCellWidth(setting.width),
contentSize: { width: 0, height: 0 },
};
}

View File

@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { CellAddress, CellValue, GridCell } from '@/components/grid/cell.js';
import { GridState } from '@/components/grid/grid.js';
import { ValidateViolation } from '@/components/grid/cell-validators.js';
import { GridColumn } from '@/components/grid/column.js';
import { GridRow } from '@/components/grid/row.js';
export type GridContext = {
selectedCell?: GridCell;
rangedCells: GridCell[];
rangedRows: GridRow[];
randedBounds: {
leftTop: CellAddress;
rightBottom: CellAddress;
};
availableBounds: {
leftTop: CellAddress;
rightBottom: CellAddress;
};
state: GridState;
rows: GridRow[];
columns: GridColumn[];
};
export type GridEvent =
GridCellValueChangeEvent |
GridCellValidationEvent
;
export type GridCellValueChangeEvent = {
type: 'cell-value-change';
column: GridColumn;
row: GridRow;
oldValue: CellValue;
newValue: CellValue;
};
export type GridCellValidationEvent = {
type: 'cell-validation';
violation?: ValidateViolation;
all: ValidateViolation[];
};

View File

@ -0,0 +1,215 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { isRef, Ref } from 'vue';
import { DataSource, SizeStyle } from '@/components/grid/grid.js';
import { CELL_ADDRESS_NONE, CellAddress, CellValue, GridCell } from '@/components/grid/cell.js';
import { GridRow } from '@/components/grid/row.js';
import { GridContext } from '@/components/grid/grid-event.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { GridColumn, GridColumnSetting } from '@/components/grid/column.js';
export function isCellElement(elem: HTMLElement): boolean {
return elem.hasAttribute('data-grid-cell');
}
export function isRowElement(elem: HTMLElement): boolean {
return elem.hasAttribute('data-grid-row');
}
export function calcCellWidth(widthSetting: SizeStyle): string {
switch (widthSetting) {
case undefined:
case 'auto': {
return 'auto';
}
default: {
return `${widthSetting}px`;
}
}
}
function getCellRowByAttribute(elem: HTMLElement): number {
const row = elem.getAttribute('data-grid-cell-row');
if (row === null) {
throw new Error('data-grid-cell-row attribute not found');
}
return Number(row);
}
function getCellColByAttribute(elem: HTMLElement): number {
const col = elem.getAttribute('data-grid-cell-col');
if (col === null) {
throw new Error('data-grid-cell-col attribute not found');
}
return Number(col);
}
export function getCellAddress(elem: HTMLElement, parentNodeCount = 10): CellAddress {
let node = elem;
for (let i = 0; i < parentNodeCount; i++) {
if (!node.parentElement) {
break;
}
if (isCellElement(node) && isRowElement(node.parentElement)) {
const row = getCellRowByAttribute(node);
const col = getCellColByAttribute(node);
return { row, col };
}
node = node.parentElement;
}
return CELL_ADDRESS_NONE;
}
export function getCellElement(elem: HTMLElement, parentNodeCount = 10): HTMLElement | null {
let node = elem;
for (let i = 0; i < parentNodeCount; i++) {
if (isCellElement(node)) {
return node;
}
if (!node.parentElement) {
break;
}
node = node.parentElement;
}
return null;
}
export function equalCellAddress(a: CellAddress, b: CellAddress): boolean {
return a.row === b.row && a.col === b.col;
}
/**
*
*/
export function copyGridDataToClipboard(
gridItems: Ref<DataSource[]> | DataSource[],
context: GridContext,
) {
const items = isRef(gridItems) ? gridItems.value : gridItems;
const lines = Array.of<string>();
const bounds = context.randedBounds;
for (let row = bounds.leftTop.row; row <= bounds.rightBottom.row; row++) {
const rowItems = Array.of<string>();
for (let col = bounds.leftTop.col; col <= bounds.rightBottom.col; col++) {
const { bindTo, events } = context.columns[col].setting;
const value = items[row][bindTo];
const transformValue = events?.copy
? events.copy(value)
: typeof value === 'object' || Array.isArray(value)
? JSON.stringify(value)
: value?.toString() ?? '';
rowItems.push(transformValue);
}
lines.push(rowItems.join('\t'));
}
const text = lines.join('\n');
copyToClipboard(text);
if (_DEV_) {
console.log(`Copied to clipboard: ${text}`);
}
}
/**
*
* 使
*/
export async function pasteToGridFromClipboard(
context: GridContext,
callback: (row: GridRow, col: GridColumn, parsedValue: CellValue) => void,
) {
function parseValue(value: string, setting: GridColumnSetting): CellValue {
if (setting.events?.paste) {
return setting.events.paste(value);
} else {
switch (setting.type) {
case 'number': {
return Number(value);
}
case 'boolean': {
return value === 'true';
}
default: {
return value;
}
}
}
}
const clipBoardText = await navigator.clipboard.readText();
if (_DEV_) {
console.log(`Paste from clipboard: ${clipBoardText}`);
}
const bounds = context.randedBounds;
const lines = clipBoardText.replace(/\r/g, '')
.split('\n')
.map(it => it.split('\t'));
if (lines.length === 1 && lines[0].length === 1) {
// 単独文字列の場合は選択範囲全体に同じテキストを貼り付ける
const ranges = context.rangedCells;
for (const cell of ranges) {
if (cell.column.setting.editable) {
callback(cell.row, cell.column, parseValue(lines[0][0], cell.column.setting));
}
}
} else {
// 表形式文字列の場合は表形式にパースし、選択範囲に合うように貼り付ける
const offsetRow = bounds.leftTop.row;
const offsetCol = bounds.leftTop.col;
const { columns, rows } = context;
for (let row = bounds.leftTop.row; row <= bounds.rightBottom.row; row++) {
const rowIdx = row - offsetRow;
if (lines.length <= rowIdx) {
// クリップボードから読んだ二次元配列よりも選択範囲の方が大きい場合、貼り付け操作を打ち切る
break;
}
const items = lines[rowIdx];
for (let col = bounds.leftTop.col; col <= bounds.rightBottom.col; col++) {
const colIdx = col - offsetCol;
if (items.length <= colIdx) {
// クリップボードから読んだ二次元配列よりも選択範囲の方が大きい場合、貼り付け操作を打ち切る
break;
}
if (columns[col].setting.editable) {
callback(rows[row], columns[col], parseValue(items[colIdx], columns[col].setting));
}
}
}
}
}
/**
*
* 使
*/
export function removeDataFromGrid(
context: GridContext,
callback: (cell: GridCell) => void,
) {
for (const cell of context.rangedCells) {
const { editable, events } = cell.column.setting;
if (editable) {
if (events?.delete) {
events.delete(cell, context);
} else {
callback(cell);
}
}
}
}

View File

@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { EventEmitter } from 'eventemitter3';
import { CellValue, GridCellSetting } from '@/components/grid/cell.js';
import { GridColumnSetting } from '@/components/grid/column.js';
import { GridRowSetting } from '@/components/grid/row.js';
export type GridSetting = {
row?: GridRowSetting;
cols: GridColumnSetting[];
cells?: GridCellSetting;
};
export type DataSource = Record<string, CellValue>;
export type GridState =
'normal' |
'cellSelecting' |
'cellEditing' |
'colResizing' |
'colSelecting' |
'rowSelecting' |
'hidden'
;
export type Size = {
width: number;
height: number;
}
export type SizeStyle = number | 'auto' | undefined;
export type AdditionalStyle = {
className?: string;
style?: Record<string, string | number>;
}
export class GridEventEmitter extends EventEmitter<{
'forceRefreshContentSize': void;
}> {
}

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { AdditionalStyle } from '@/components/grid/grid.js';
import { GridCell } from '@/components/grid/cell.js';
import { GridColumn } from '@/components/grid/column.js';
import { MenuItem } from '@/types/menu.js';
import { GridContext } from '@/components/grid/grid-event.js';
export const defaultGridRowSetting: Required<GridRowSetting> = {
showNumber: true,
selectable: true,
minimumDefinitionCount: 100,
styleRules: [],
contextMenuFactory: () => [],
events: {},
};
export type GridRowStyleRuleConditionParams = {
row: GridRow,
targetCols: GridColumn[],
cells: GridCell[]
};
export type GridRowStyleRule = {
condition: (params: GridRowStyleRuleConditionParams) => boolean;
applyStyle: AdditionalStyle;
}
export type GridRowContextMenuFactory = (row: GridRow, context: GridContext) => MenuItem[];
export type GridRowSetting = {
showNumber?: boolean;
selectable?: boolean;
minimumDefinitionCount?: number;
styleRules?: GridRowStyleRule[];
contextMenuFactory?: GridRowContextMenuFactory;
events?: {
delete?: (rows: GridRow[]) => void;
}
}
export type GridRow = {
index: number;
ranged: boolean;
using: boolean;
setting: GridRowSetting;
additionalStyles: AdditionalStyle[];
}
export function createRow(index: number, using: boolean, setting: GridRowSetting): GridRow {
return {
index,
ranged: false,
using: using,
setting,
additionalStyles: [],
};
}
export function resetRow(row: GridRow): void {
row.ranged = false;
row.using = false;
row.additionalStyles = [];
}

View File

@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { computed, h, ref } from 'vue';
import MkLoading from '@/components/global/MkLoading.vue';
export const useLoading = (props?: {
static?: boolean;
inline?: boolean;
colored?: boolean;
mini?: boolean;
em?: boolean;
}) => {
const showingCnt = ref(0);
const show = () => {
showingCnt.value++;
};
const close = (force?: boolean) => {
if (force) {
showingCnt.value = 0;
} else {
showingCnt.value = Math.max(0, showingCnt.value - 1);
}
};
const scope = <T>(fn: () => T) => {
show();
const result = fn();
if (result instanceof Promise) {
return result.finally(() => close());
} else {
close();
return result;
}
};
const showing = computed(() => showingCnt.value > 0);
const component = computed(() => showing.value ? h(MkLoading, props) : null);
return {
show,
close,
scope,
component,
showing,
};
};

View File

@ -20,6 +20,7 @@
worker-src 'self'; worker-src 'self';
script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://*.recaptcha.net https://*.gstatic.com https://challenges.cloudflare.com https://esm.sh; script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://*.recaptcha.net https://*.gstatic.com https://challenges.cloudflare.com https://esm.sh;
style-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
font-src 'self' data:;
img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000; img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000; media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com; connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com;

View File

@ -602,6 +602,27 @@ export async function selectDriveFolder(multiple: boolean): Promise<Misskey.enti
}); });
} }
export async function selectRole(params: {
initialRoleIds?: string[],
title?: string,
infoMessage?: string,
publicOnly?: boolean,
}): Promise<
{ canceled: true; result: undefined; } |
{ canceled: false; result: Misskey.entities.Role[] }
> {
return new Promise((resolve) => {
popup(defineAsyncComponent(() => import('@/components/MkRoleSelectDialog.vue')), params, {
done: roles => {
resolve({ canceled: false, result: roles });
},
close: () => {
resolve({ canceled: true, result: undefined });
},
}, 'dispose');
});
}
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> { export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
return new Promise(resolve => { return new Promise(resolve => {
const { dispose } = popup(MkEmojiPickerDialog, { const { dispose } = popup(MkEmojiPickerDialog, {

View File

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export type RequestLogItem = {
failed: boolean;
url: string;
name: string;
error?: string;
};
export const gridSortOrderKeys = [
'name',
'category',
'aliases',
'type',
'license',
'host',
'uri',
'publicUrl',
'isSensitive',
'localOnly',
'updatedAt',
];
export type GridSortOrderKey = typeof gridSortOrderKeys[number];
export function emptyStrToUndefined(value: string | null) {
return value ? value : undefined;
}
export function emptyStrToNull(value: string) {
return value === '' ? null : value;
}
export function emptyStrToEmptyArray(value: string) {
return value === '' ? [] : value.split(' ').map(it => it.trim());
}
export function roleIdsParser(text: string): { id: string, name: string }[] {
// idとnameのペア配列をJSONで受け取る。それ以外の形式は許容しない
try {
const obj = JSON.parse(text);
if (!Array.isArray(obj)) {
return [];
}
if (!obj.every(it => typeof it === 'object' && 'id' in it && 'name' in it)) {
return [];
}
return obj.map(it => ({ id: it.id, name: it.name }));
} catch (ex) {
console.warn(ex);
return [];
}
}

View File

@ -0,0 +1,757 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkStickyContainer>
<template #default>
<div class="_gaps">
<MkFolder>
<template #icon><i class="ti ti-search"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.searchSettings }}</template>
<template #caption>
{{ i18n.ts._customEmojisManager._gridCommon.searchSettingCaption }}
</template>
<div class="_gaps">
<div :class="[[spMode ? $style.searchAreaSp : $style.searchArea]]">
<MkInput
v-model="queryName"
type="search"
autocapitalize="off"
:class="[$style.col1, $style.row1]"
@enter="onSearchRequest"
>
<template #label>name</template>
</MkInput>
<MkInput
v-model="queryCategory"
type="search"
autocapitalize="off"
:class="[$style.col2, $style.row1]"
@enter="onSearchRequest"
>
<template #label>category</template>
</MkInput>
<MkInput
v-model="queryAliases"
type="search"
autocapitalize="off"
:class="[$style.col3, $style.row1]"
@enter="onSearchRequest"
>
<template #label>aliases</template>
</MkInput>
<MkInput
v-model="queryType"
type="search"
autocapitalize="off"
:class="[$style.col1, $style.row2]"
@enter="onSearchRequest"
>
<template #label>type</template>
</MkInput>
<MkInput
v-model="queryLicense"
type="search"
autocapitalize="off"
:class="[$style.col2, $style.row2]"
@enter="onSearchRequest"
>
<template #label>license</template>
</MkInput>
<MkSelect
v-model="querySensitive"
:class="[$style.col3, $style.row2]"
>
<template #label>sensitive</template>
<option :value="null">-</option>
<option :value="true">true</option>
<option :value="false">false</option>
</MkSelect>
<MkSelect
v-model="queryLocalOnly"
:class="[$style.col1, $style.row3]"
>
<template #label>localOnly</template>
<option :value="null">-</option>
<option :value="true">true</option>
<option :value="false">false</option>
</MkSelect>
<MkInput
v-model="queryUpdatedAtFrom"
type="date"
autocapitalize="off"
:class="[$style.col2, $style.row3]"
@enter="onSearchRequest"
>
<template #label>updatedAt(from)</template>
</MkInput>
<MkInput
v-model="queryUpdatedAtTo"
type="date"
autocapitalize="off"
:class="[$style.col3, $style.row3]"
@enter="onSearchRequest"
>
<template #label>updatedAt(to)</template>
</MkInput>
<MkInput
v-model="queryRolesText"
type="text"
readonly
autocapitalize="off"
:class="[$style.col1, $style.row4]"
@click="onQueryRolesEditClicked"
>
<template #label>role</template>
<template #suffix><span class="ti ti-pencil"/></template>
</MkInput>
</div>
<MkFolder :spacerMax="8" :spacerMin="8">
<template #icon><i class="ti ti-arrows-sort"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
<MkSortOrderEditor
:baseOrderKeyNames="gridSortOrderKeys"
:currentOrders="sortOrders"
@update="onSortOrderUpdate"
/>
</MkFolder>
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
<MkButton primary @click="onSearchRequest">
{{ i18n.ts.search }}
</MkButton>
<MkButton @click="onQueryResetButtonClicked">
{{ i18n.ts.reset }}
</MkButton>
</div>
</div>
</MkFolder>
<XRegisterLogsFolder :logs="requestLogs"/>
<component :is="loadingHandler.component.value" v-if="loadingHandler.showing.value"/>
<template v-else>
<div v-if="gridItems.length === 0" style="text-align: center">
{{ i18n.ts._customEmojisManager._local._list.emojisNothing }}
</div>
<template v-else>
<div :class="$style.gridArea">
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
</div>
<div :class="$style.footer">
<div :class="$style.left">
<MkButton danger style="margin-right: auto" @click="onDeleteButtonClicked">
{{ i18n.ts.delete }} ({{ deleteItemsCount }})
</MkButton>
</div>
<div :class="$style.center">
<MkPagingButtons :current="currentPage" :max="allPages" :buttonCount="5" @pageChanged="onPageChanged"/>
</div>
<div :class="$style.right">
<MkButton primary :disabled="updateButtonDisabled" @click="onUpdateButtonClicked">
{{ i18n.ts.update }} ({{ updatedItemsCount }})
</MkButton>
<MkButton @click="onGridResetButtonClicked">{{ i18n.ts.reset }}</MkButton>
</div>
</div>
</template>
</template>
</div>
</template>
</MkStickyContainer>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, useCssModule } from 'vue';
import * as Misskey from 'misskey-js';
import * as os from '@/os.js';
import {
emptyStrToEmptyArray,
emptyStrToNull,
emptyStrToUndefined,
GridSortOrderKey,
gridSortOrderKeys,
RequestLogItem,
roleIdsParser,
} from '@/pages/admin/custom-emojis-manager.impl.js';
import MkGrid from '@/components/grid/MkGrid.vue';
import { i18n } from '@/i18n.js';
import MkInput from '@/components/MkInput.vue';
import MkButton from '@/components/MkButton.vue';
import { validators } from '@/components/grid/cell-validators.js';
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import MkPagingButtons from '@/components/MkPagingButtons.vue';
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkSelect from '@/components/MkSelect.vue';
import { deviceKind } from '@/scripts/device-kind.js';
import { GridSetting } from '@/components/grid/grid.js';
import { selectFile } from '@/scripts/select-file.js';
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
import { useLoading } from "@/components/hook/useLoading.js";
type GridItem = {
checked: boolean;
id: string;
url: string;
name: string;
host: string;
category: string;
aliases: string;
license: string;
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: { id: string, name: string }[];
fileId?: string;
updatedAt: string | null;
publicUrl?: string | null;
originalUrl?: string | null;
type: string | null;
}
function setupGrid(): GridSetting {
const $style = useCssModule();
const required = validators.required();
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
const unique = validators.unique();
return {
row: {
showNumber: true,
selectable: true,
// 100
minimumDefinitionCount: 100,
styleRules: [
{
//
condition: ({ row }) => JSON.stringify(gridItems.value[row.index]) !== JSON.stringify(originGridItems.value[row.index]),
applyStyle: { className: $style.changedRow },
},
{
//
condition: ({ cells }) => cells.some(it => !it.violation.valid),
applyStyle: { className: $style.violationRow },
},
],
//
contextMenuFactory: (row, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRows,
icon: 'ti ti-copy',
action: () => copyGridDataToClipboard(gridItems, context),
},
{
type: 'button',
text: i18n.ts._customEmojisManager._local._list.markAsDeleteTargetRows,
icon: 'ti ti-trash',
action: () => {
for (const rangedRow of context.rangedRows) {
gridItems.value[rangedRow.index].checked = true;
}
},
},
];
},
events: {
delete(rows) {
//
for (const row of rows) {
gridItems.value[row.index].checked = true;
}
},
},
},
cols: [
{ bindTo: 'checked', icon: 'ti-trash', type: 'boolean', editable: true, width: 34 },
{
bindTo: 'url', icon: 'ti-icons', type: 'image', editable: true, width: 'auto', validators: [required],
async customValueEditor(row, col, value, cellElement) {
const file = await selectFile(cellElement);
gridItems.value[row.index].url = file.url;
gridItems.value[row.index].fileId = file.id;
return file.url;
},
},
{
bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140,
validators: [required, regex, unique],
},
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
{
bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 140,
valueTransformer(row) {
// IDID
return gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction
.map((it) => it.name)
.join(',');
},
async customValueEditor(row) {
// ID使
const current = gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction;
const result = await os.selectRole({
initialRoleIds: current.map(it => it.id),
title: i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction,
infoMessage: i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription,
publicOnly: true,
});
if (result.canceled) {
return current;
}
const transform = result.result.map(it => ({ id: it.id, name: it.name }));
gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction = transform;
return transform;
},
events: {
paste: roleIdsParser,
delete(cell) {
// undefined
gridItems.value[cell.row.index].roleIdsThatCanBeUsedThisEmojiAsReaction = [];
},
},
},
{ bindTo: 'type', type: 'text', editable: false, width: 90 },
{ bindTo: 'updatedAt', type: 'text', editable: false, width: 'auto' },
{ bindTo: 'publicUrl', type: 'text', editable: false, width: 180 },
{ bindTo: 'originalUrl', type: 'text', editable: false, width: 180 },
],
cells: {
//
contextMenuFactory(col, row, value, context) {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRanges,
icon: 'ti ti-copy',
action: () => {
return copyGridDataToClipboard(gridItems, context);
},
},
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.deleteSelectionRanges,
icon: 'ti ti-trash',
action: () => {
removeDataFromGrid(context, (cell) => {
gridItems.value[cell.row.index][cell.column.setting.bindTo] = undefined;
});
},
},
{
type: 'button',
text: i18n.ts._customEmojisManager._local._list.markAsDeleteTargetRanges,
icon: 'ti ti-trash',
action: () => {
for (const rowIdx of [...new Set(context.rangedCells.map(it => it.row.index)).values()]) {
gridItems.value[rowIdx].checked = true;
}
},
},
];
},
},
};
}
const loadingHandler = useLoading();
const customEmojis = ref<Misskey.entities.EmojiDetailedAdmin[]>([]);
const allPages = ref<number>(0);
const currentPage = ref<number>(0);
const queryName = ref<string | null>(null);
const queryCategory = ref<string | null>(null);
const queryAliases = ref<string | null>(null);
const queryType = ref<string | null>(null);
const queryLicense = ref<string | null>(null);
const queryUpdatedAtFrom = ref<string | null>(null);
const queryUpdatedAtTo = ref<string | null>(null);
const querySensitive = ref<string | null>(null);
const queryLocalOnly = ref<string | null>(null);
const queryRoles = ref<{ id: string, name: string }[]>([]);
const previousQuery = ref<string | undefined>(undefined);
const sortOrders = ref<SortOrder<GridSortOrderKey>[]>([]);
const requestLogs = ref<RequestLogItem[]>([]);
const gridItems = ref<GridItem[]>([]);
const originGridItems = ref<GridItem[]>([]);
const updateButtonDisabled = ref<boolean>(false);
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
const queryRolesText = computed(() => queryRoles.value.map(it => it.name).join(','));
const updatedItemsCount = computed(() => {
return gridItems.value.filter((it, idx) => !it.checked && JSON.stringify(it) !== JSON.stringify(originGridItems.value[idx])).length;
});
const deleteItemsCount = computed(() => gridItems.value.filter(it => it.checked).length);
async function onUpdateButtonClicked() {
const _items = gridItems.value;
const _originItems = originGridItems.value;
if (_items.length !== _originItems.length) {
throw new Error('The number of items has been changed. Please refresh the page and try again.');
}
const updatedItems = _items.filter((it, idx) => !it.checked && JSON.stringify(it) !== JSON.stringify(_originItems[idx]));
if (updatedItems.length === 0) {
await os.alert({
type: 'info',
text: i18n.ts._customEmojisManager._local._list.alertUpdateEmojisNothingDescription,
});
return;
}
const confirm = await os.confirm({
type: 'info',
title: i18n.ts._customEmojisManager._local._list.confirmUpdateEmojisTitle,
text: i18n.tsx._customEmojisManager._local._list.confirmUpdateEmojisDescription({ count: updatedItems.length }),
});
if (confirm.canceled) {
return;
}
const action = () => {
return updatedItems.map(item =>
misskeyApi(
'admin/emoji/update',
{
// eslint-disable-next-line
id: item.id!,
name: item.name,
category: emptyStrToNull(item.category),
aliases: emptyStrToEmptyArray(item.aliases),
license: emptyStrToNull(item.license),
isSensitive: item.isSensitive,
localOnly: item.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: item.roleIdsThatCanBeUsedThisEmojiAsReaction.map(it => it.id),
fileId: item.fileId,
})
.then(() => ({ item, success: true, err: undefined }))
.catch(err => ({ item, success: false, err })),
);
};
const result = await os.promiseDialog(Promise.all(action()));
const failedItems = result.filter(it => !it.success);
if (failedItems.length > 0) {
await os.alert({
type: 'error',
title: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedTitle,
text: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedDescription,
});
}
requestLogs.value = result.map(it => ({
failed: !it.success,
url: it.item.url,
name: it.item.name,
error: it.err ? JSON.stringify(it.err) : undefined,
}));
await refreshCustomEmojis();
}
async function onDeleteButtonClicked() {
const _items = gridItems.value;
const _originItems = originGridItems.value;
if (_items.length !== _originItems.length) {
throw new Error('The number of items has been changed. Please refresh the page and try again.');
}
const deleteItems = _items.filter((it) => it.checked);
if (deleteItems.length === 0) {
await os.alert({
type: 'info',
text: i18n.ts._customEmojisManager._local._list.alertDeleteEmojisNothingDescription,
});
return;
}
const confirm = await os.confirm({
type: 'info',
title: i18n.ts._customEmojisManager._local._list.confirmDeleteEmojisTitle,
text: i18n.tsx._customEmojisManager._local._list.confirmDeleteEmojisDescription({ count: deleteItems.length }),
});
if (confirm.canceled) {
return;
}
async function action() {
const deleteIds = deleteItems.map(it => it.id!);
await misskeyApi('admin/emoji/delete-bulk', { ids: deleteIds });
}
await os.promiseDialog(
action(),
);
}
function onGridResetButtonClicked() {
refreshGridItems();
}
async function onQueryRolesEditClicked() {
const result = await os.selectRole({
initialRoleIds: queryRoles.value.map(it => it.id),
title: i18n.ts._customEmojisManager._local._list.dialogSelectRoleTitle,
publicOnly: true,
});
if (result.canceled) {
return;
}
queryRoles.value = result.result;
}
function onSortOrderUpdate(_sortOrders: SortOrder<GridSortOrderKey>[]) {
sortOrders.value = _sortOrders;
}
async function onSearchRequest() {
await refreshCustomEmojis();
}
function onQueryResetButtonClicked() {
queryName.value = null;
queryCategory.value = null;
queryAliases.value = null;
queryType.value = null;
queryLicense.value = null;
queryUpdatedAtFrom.value = null;
queryUpdatedAtTo.value = null;
querySensitive.value = null;
queryLocalOnly.value = null;
queryRoles.value = [];
}
async function onPageChanged(pageNumber: number) {
currentPage.value = pageNumber;
await refreshCustomEmojis();
}
function onGridEvent(event: GridEvent) {
switch (event.type) {
case 'cell-validation':
onGridCellValidation(event);
break;
case 'cell-value-change':
onGridCellValueChange(event);
break;
}
}
function onGridCellValidation(event: GridCellValidationEvent) {
updateButtonDisabled.value = event.all.filter(it => !it.valid).length > 0;
}
function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue;
}
}
async function refreshCustomEmojis() {
const limit = 100;
const query: Misskey.entities.V2AdminEmojiListRequest['query'] = {
name: emptyStrToUndefined(queryName.value),
type: emptyStrToUndefined(queryType.value),
aliases: emptyStrToUndefined(queryAliases.value),
category: emptyStrToUndefined(queryCategory.value),
license: emptyStrToUndefined(queryLicense.value),
isSensitive: querySensitive.value ? Boolean(querySensitive.value).valueOf() : undefined,
localOnly: queryLocalOnly.value ? Boolean(queryLocalOnly.value).valueOf() : undefined,
updatedAtFrom: emptyStrToUndefined(queryUpdatedAtFrom.value),
updatedAtTo: emptyStrToUndefined(queryUpdatedAtTo.value),
roleIds: queryRoles.value.map(it => it.id),
hostType: 'local',
};
if (JSON.stringify(query) !== previousQuery.value) {
currentPage.value = 1;
}
const result = await loadingHandler.scope(() => misskeyApi('v2/admin/emoji/list', {
query: query,
limit: limit,
page: currentPage.value,
sortKeys: sortOrders.value.map(({ key, direction }) => `${direction}${key}` as any),
}));
customEmojis.value = result.emojis;
allPages.value = result.allPages;
previousQuery.value = JSON.stringify(query);
refreshGridItems();
}
function refreshGridItems() {
gridItems.value = customEmojis.value.map(it => ({
checked: false,
id: it.id,
fileId: undefined,
url: it.publicUrl,
name: it.name,
host: it.host ?? '',
category: it.category ?? '',
aliases: it.aliases.join(','),
license: it.license ?? '',
isSensitive: it.isSensitive,
localOnly: it.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: it.roleIdsThatCanBeUsedThisEmojiAsReaction,
updatedAt: it.updatedAt,
publicUrl: it.publicUrl,
originalUrl: it.originalUrl,
type: it.type,
}));
originGridItems.value = JSON.parse(JSON.stringify(gridItems.value));
}
onMounted(async () => {
await refreshCustomEmojis();
});
</script>
<style module lang="scss">
.violationRow {
background-color: var(--MI_THEME-infoWarnBg);
}
.changedRow {
background-color: var(--MI_THEME-infoBg);
}
.editedRow {
background-color: var(--MI_THEME-infoBg);
}
.row1 {
grid-row: 1 / 2;
}
.row2 {
grid-row: 2 / 3;
}
.row3 {
grid-row: 3 / 4;
}
.row4 {
grid-row: 4 / 5;
}
.col1 {
grid-column: 1 / 2;
}
.col2 {
grid-column: 2 / 3;
}
.col3 {
grid-column: 3 / 4;
}
.searchArea {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 16px;
}
.searchAreaSp {
display: flex;
flex-direction: column;
gap: 8px;
}
.searchButtons {
display: flex;
justify-content: flex-end;
align-items: flex-end;
gap: 8px;
}
.searchButtonsSp {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
.gridArea {
padding-top: 8px;
padding-bottom: 8px;
}
.footer {
background-color: var(--MI_THEME-bg);
position: sticky;
left:0;
bottom:0;
z-index: 1;
// stickypadding
margin-top: calc(var(--MI-margin) * -1);
margin-bottom: calc(var(--MI-margin) * -1);
padding-top: var(--MI-margin);
padding-bottom: var(--MI-margin);
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
& .left {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
}
& .center {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
& .right {
display: flex;
align-items: center;
justify-content: flex-end;
flex-direction: row;
gap: 8px;
}
}
.divider {
margin: 8px 0;
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View File

@ -0,0 +1,477 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div class="_gaps">
<MkFolder>
<template #icon><i class="ti ti-settings"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._local._register.uploadSettingTitle }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.uploadSettingDescription }}</template>
<div class="_gaps">
<MkSelect v-model="selectedFolderId">
<template #label>{{ i18n.ts.uploadFolder }}</template>
<option v-for="folder in uploadFolders" :key="folder.id" :value="folder.id">
{{ folder.name }}
</option>
</MkSelect>
<MkSwitch v-model="keepOriginalUploading">
<template #label>{{ i18n.ts.keepOriginalUploading }}</template>
<template #caption>{{ i18n.ts.keepOriginalUploadingDescription }}</template>
</MkSwitch>
<MkSwitch v-model="directoryToCategory">
<template #label>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryLabel }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryCaption }}</template>
</MkSwitch>
</div>
</MkFolder>
<XRegisterLogsFolder :logs="requestLogs"/>
<div
:class="[$style.uploadBox, [isDragOver ? $style.dragOver : {}]]"
@dragover.prevent="isDragOver = true"
@dragleave.prevent="isDragOver = false"
@drop.prevent.stop="onDrop"
>
<div style="margin-top: 1em">
{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaCaption }}
</div>
<ul>
<li>{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList1 }}</li>
<li><a @click.prevent="onFileSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList2 }}</a></li>
<li><a @click.prevent="onDriveSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList3 }}</a></li>
</ul>
</div>
<div v-if="gridItems.length > 0" :class="$style.gridArea">
<MkGrid
:data="gridItems"
:settings="setupGrid()"
@event="onGridEvent"
/>
</div>
<div v-if="gridItems.length > 0" :class="$style.footer">
<MkButton primary :disabled="registerButtonDisabled" @click="onRegistryClicked">
{{ i18n.ts.registration }}
</MkButton>
<MkButton @click="onClearClicked">
{{ i18n.ts.clear }}
</MkButton>
</div>
</div>
</template>
<script setup lang="ts">
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as Misskey from 'misskey-js';
import { onMounted, ref, useCssModule } from 'vue';
import { misskeyApi } from '@/scripts/misskey-api.js';
import {
emptyStrToEmptyArray,
emptyStrToNull,
RequestLogItem,
roleIdsParser,
} from '@/pages/admin/custom-emojis-manager.impl.js';
import MkGrid from '@/components/grid/MkGrid.vue';
import { i18n } from '@/i18n.js';
import MkSelect from '@/components/MkSelect.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import { defaultStore } from '@/store.js';
import MkFolder from '@/components/MkFolder.vue';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os.js';
import { validators } from '@/components/grid/cell-validators.js';
import { chooseFileFromDrive, chooseFileFromPc } from '@/scripts/select-file.js';
import { uploadFile } from '@/scripts/upload.js';
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
import { GridSetting } from '@/components/grid/grid.js';
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
import { GridRow } from '@/components/grid/row.js';
const MAXIMUM_EMOJI_REGISTER_COUNT = 100;
type FolderItem = {
id?: string;
name: string;
};
type GridItem = {
fileId: string;
url: string;
name: string;
host: string;
category: string;
aliases: string;
license: string;
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: { id: string, name: string }[];
type: string | null;
}
function setupGrid(): GridSetting {
const $style = useCssModule();
const required = validators.required();
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
const unique = validators.unique();
function removeRows(rows: GridRow[]) {
const idxes = [...new Set(rows.map(it => it.index))];
gridItems.value = gridItems.value.filter((_, i) => !idxes.includes(i));
}
return {
row: {
showNumber: true,
selectable: true,
minimumDefinitionCount: 100,
styleRules: [
{
// 1
condition: ({ cells }) => cells.some(it => !it.violation.valid),
applyStyle: { className: $style.violationRow },
},
],
//
contextMenuFactory: (row, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRows,
icon: 'ti ti-copy',
action: () => copyGridDataToClipboard(gridItems, context),
},
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.deleteSelectionRows,
icon: 'ti ti-trash',
action: () => removeRows(context.rangedRows),
},
];
},
events: {
delete(rows) {
removeRows(rows);
},
},
},
cols: [
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto', validators: [required] },
{
bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140,
validators: [required, regex, unique],
},
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
{
bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 140,
valueTransformer: (row) => {
// IDID
return gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction
.map((it) => it.name)
.join(',');
},
customValueEditor: async (row) => {
// ID使
const current = gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction;
const result = await os.selectRole({
initialRoleIds: current.map(it => it.id),
title: i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction,
infoMessage: i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription,
publicOnly: true,
});
if (result.canceled) {
return current;
}
const transform = result.result.map(it => ({ id: it.id, name: it.name }));
gridItems.value[row.index].roleIdsThatCanBeUsedThisEmojiAsReaction = transform;
return transform;
},
events: {
paste: roleIdsParser,
delete(cell) {
// undefined
gridItems.value[cell.row.index].roleIdsThatCanBeUsedThisEmojiAsReaction = [];
},
},
},
{ bindTo: 'type', type: 'text', editable: false, width: 90 },
],
cells: {
//
contextMenuFactory: (col, row, value, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRanges,
icon: 'ti ti-copy',
action: () => copyGridDataToClipboard(gridItems, context),
},
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.deleteSelectionRanges,
icon: 'ti ti-trash',
action: () => removeRows(context.rangedCells.map(it => it.row)),
},
];
},
},
};
}
const uploadFolders = ref<FolderItem[]>([]);
const gridItems = ref<GridItem[]>([]);
const selectedFolderId = ref(defaultStore.state.uploadFolder);
const keepOriginalUploading = ref(defaultStore.state.keepOriginalUploading);
const directoryToCategory = ref<boolean>(false);
const registerButtonDisabled = ref<boolean>(false);
const requestLogs = ref<RequestLogItem[]>([]);
const isDragOver = ref<boolean>(false);
async function onRegistryClicked() {
const dialogSelection = await os.confirm({
type: 'info',
title: i18n.ts._customEmojisManager._local._register.confirmRegisterEmojisTitle,
text: i18n.tsx._customEmojisManager._local._register.confirmRegisterEmojisDescription({ count: MAXIMUM_EMOJI_REGISTER_COUNT }),
});
if (dialogSelection.canceled) {
return;
}
const items = gridItems.value;
const upload = () => {
return items.slice(0, MAXIMUM_EMOJI_REGISTER_COUNT)
.map(item =>
misskeyApi(
'admin/emoji/add', {
name: item.name,
category: emptyStrToNull(item.category),
aliases: emptyStrToEmptyArray(item.aliases),
license: emptyStrToNull(item.license),
isSensitive: item.isSensitive,
localOnly: item.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: item.roleIdsThatCanBeUsedThisEmojiAsReaction.map(it => it.id),
fileId: item.fileId!,
})
.then(() => ({ item, success: true, err: undefined }))
.catch(err => ({ item, success: false, err })),
);
};
const result = await os.promiseDialog(Promise.all(upload()));
const failedItems = result.filter(it => !it.success);
if (failedItems.length > 0) {
await os.alert({
type: 'error',
title: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedTitle,
text: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedDescription,
});
}
requestLogs.value = result.map(it => ({
failed: !it.success,
url: it.item.url,
name: it.item.name,
error: it.err ? JSON.stringify(it.err) : undefined,
}));
//
const successItems = result.filter(it => it.success).map(it => it.item);
gridItems.value = gridItems.value.filter(it => !successItems.includes(it));
}
async function onClearClicked() {
const result = await os.confirm({
type: 'warning',
title: i18n.ts._customEmojisManager._local._register.confirmClearEmojisTitle,
text: i18n.ts._customEmojisManager._local._register.confirmClearEmojisDescription,
});
if (!result.canceled) {
gridItems.value = [];
}
}
async function onDrop(ev: DragEvent) {
isDragOver.value = false;
const droppedFiles = await extractDroppedItems(ev).then(it => flattenDroppedFiles(it));
const confirm = await os.confirm({
type: 'info',
title: i18n.ts._customEmojisManager._local._register.confirmUploadEmojisTitle,
text: i18n.tsx._customEmojisManager._local._register.confirmUploadEmojisDescription({ count: droppedFiles.length }),
});
if (confirm.canceled) {
return;
}
const uploadedItems = Array.of<{ droppedFile: DroppedFile, driveFile: Misskey.entities.DriveFile }>();
try {
uploadedItems.push(
...await os.promiseDialog(
Promise.all(
droppedFiles.map(async (it) => ({
droppedFile: it,
driveFile: await uploadFile(
it.file,
selectedFolderId.value,
it.file.name.replace(/\.[^.]+$/, ''),
keepOriginalUploading.value,
),
}),
),
),
() => {
},
() => {
},
),
);
} catch (err) {
//
return;
}
const items = uploadedItems.map(({ droppedFile, driveFile }) => {
const item = fromDriveFile(driveFile);
if (directoryToCategory.value) {
item.category = droppedFile.path
.replace(/^\//, '')
.replace(/\/[^/]+$/, '')
.replace(droppedFile.file.name, '');
}
return item;
});
gridItems.value.push(...items);
}
async function onFileSelectClicked() {
const driveFiles = await chooseFileFromPc(
true,
{
uploadFolder: selectedFolderId.value,
keepOriginal: keepOriginalUploading.value,
//
nameConverter: (file) => file.name.replace(/\.[a-zA-Z0-9]+$/, ''),
},
);
gridItems.value.push(...driveFiles.map(fromDriveFile));
}
async function onDriveSelectClicked() {
const driveFiles = await chooseFileFromDrive(true);
gridItems.value.push(...driveFiles.map(fromDriveFile));
}
function onGridEvent(event: GridEvent) {
switch (event.type) {
case 'cell-validation':
onGridCellValidation(event);
break;
case 'cell-value-change':
onGridCellValueChange(event);
break;
}
}
function onGridCellValidation(event: GridCellValidationEvent) {
registerButtonDisabled.value = event.all.filter(it => !it.valid).length > 0;
}
function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue;
}
}
function fromDriveFile(it: Misskey.entities.DriveFile): GridItem {
return {
fileId: it.id,
url: it.url,
name: it.name.replace(/(\.[a-zA-Z0-9]+)+$/, ''),
host: '',
category: '',
aliases: '',
license: '',
isSensitive: it.isSensitive,
localOnly: false,
roleIdsThatCanBeUsedThisEmojiAsReaction: [],
type: it.type,
};
}
async function refreshUploadFolders() {
const result = await misskeyApi('drive/folders', {});
uploadFolders.value = Array.of<FolderItem>({ name: '-' }, ...result);
}
onMounted(async () => {
await refreshUploadFolders();
});
</script>
<style module lang="scss">
.violationRow {
background-color: var(--MI_THEME-infoWarnBg);
}
.uploadBox {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: auto;
border: 0.5px dotted var(--MI_THEME-accentedBg);
border-radius: var(--MI-radius);
background-color: var(--MI_THEME-accentedBg);
box-sizing: border-box;
&.dragOver {
cursor: copy;
}
}
.gridArea {
padding-top: 8px;
padding-bottom: 8px;
}
.footer {
background-color: var(--MI_THEME-bg);
position: sticky;
left:0;
bottom:0;
z-index: 1;
// stickypadding
margin-top: calc(var(--MI-margin) * -1);
margin-bottom: calc(var(--MI-margin) * -1);
padding-top: var(--MI-margin);
padding-bottom: var(--MI-margin);
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: flex-end;
}
</style>

View File

@ -0,0 +1,36 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div class="_gaps" :class="$style.root">
<MkTab v-model="modeTab" style="margin-bottom: var(--margin);">
<option value="list">{{ i18n.ts._customEmojisManager._local.tabTitleList }}</option>
<option value="register">{{ i18n.ts._customEmojisManager._local.tabTitleRegister }}</option>
</MkTab>
<div>
<XListComponent v-if="modeTab === 'list'"/>
<XRegisterComponent v-else/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { i18n } from '@/i18n.js';
import MkTab from '@/components/MkTab.vue';
import XListComponent from '@/pages/admin/custom-emojis-manager.local.list.vue';
import XRegisterComponent from '@/pages/admin/custom-emojis-manager.local.register.vue';
type PageMode = 'list' | 'register';
const modeTab = ref<PageMode>('list');
</script>
<style module lang="scss">
.root {
padding: var(--MI-margin);
}
</style>

View File

@ -0,0 +1,102 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkFolder>
<template #icon><i class="ti ti-notes"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
<template #caption>
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
</template>
<div>
<div v-if="logs.length > 0" style="display:flex; flex-direction: column; overflow-y: scroll; gap: 16px;">
<MkSwitch v-model="showingSuccessLogs">
<template #label>{{ i18n.ts._customEmojisManager._logs.showSuccessLogSwitch }}</template>
</MkSwitch>
<div>
<div v-if="filteredLogs.length > 0">
<MkGrid
:data="filteredLogs"
:settings="setupGrid()"
/>
</div>
<div v-else>
{{ i18n.ts._customEmojisManager._logs.failureLogNothing }}
</div>
</div>
</div>
<div v-else>
{{ i18n.ts._customEmojisManager._logs.logNothing }}
</div>
</div>
</MkFolder>
</template>
<script setup lang="ts">
import { computed, ref, toRefs } from 'vue';
import { i18n } from '@/i18n.js';
import { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
import MkGrid from '@/components/grid/MkGrid.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import { GridSetting } from '@/components/grid/grid.js';
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
import MkFolder from '@/components/MkFolder.vue';
function setupGrid(): GridSetting {
return {
row: {
showNumber: false,
selectable: false,
contextMenuFactory: (row, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRows,
icon: 'ti ti-copy',
action: () => copyGridDataToClipboard(logs, context),
},
];
},
},
cols: [
{ bindTo: 'failed', title: 'failed', type: 'boolean', editable: false, width: 50 },
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 140 },
{ bindTo: 'error', title: 'log', type: 'text', editable: false, width: 'auto' },
],
cells: {
contextMenuFactory: (col, row, value, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._gridCommon.copySelectionRanges,
icon: 'ti ti-copy',
action: () => copyGridDataToClipboard(logs, context),
},
];
},
},
};
}
const props = defineProps<{
logs: RequestLogItem[];
}>();
const { logs } = toRefs(props);
const showingSuccessLogs = ref<boolean>(false);
const filteredLogs = computed(() => {
const forceShowing = showingSuccessLogs.value;
return logs.value.filter((log) => forceShowing || log.failed);
});
</script>
<style module lang="scss">
</style>

View File

@ -0,0 +1,441 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkStickyContainer>
<template #default>
<div :class="$style.root" class="_gaps">
<MkFolder>
<template #icon><i class="ti ti-search"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.searchSettings }}</template>
<template #caption>
{{ i18n.ts._customEmojisManager._gridCommon.searchSettingCaption }}
</template>
<div class="_gaps">
<div :class="[[spMode ? $style.searchAreaSp : $style.searchArea]]">
<MkInput
v-model="queryName"
type="search"
autocapitalize="off"
:class="[$style.col1, $style.row1]"
@enter="onSearchRequest"
>
<template #label>name</template>
</MkInput>
<MkInput
v-model="queryHost"
type="search"
autocapitalize="off"
:class="[$style.col2, $style.row1]"
@enter="onSearchRequest"
>
<template #label>host</template>
</MkInput>
<MkInput
v-model="queryUri"
type="search"
autocapitalize="off"
:class="[$style.col1, $style.row2]"
@enter="onSearchRequest"
>
<template #label>uri</template>
</MkInput>
<MkInput
v-model="queryPublicUrl"
type="search"
autocapitalize="off"
:class="[$style.col2, $style.row2]"
@enter="onSearchRequest"
>
<template #label>publicUrl</template>
</MkInput>
</div>
<MkFolder :spacerMax="8" :spacerMin="8">
<template #icon><i class="ti ti-arrows-sort"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
<MkSortOrderEditor
:baseOrderKeyNames="gridSortOrderKeys"
:currentOrders="sortOrders"
@update="onSortOrderUpdate"
/>
</MkFolder>
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
<MkButton primary @click="onSearchRequest">
{{ i18n.ts.search }}
</MkButton>
<MkButton @click="onQueryResetButtonClicked">
{{ i18n.ts.reset }}
</MkButton>
</div>
</div>
</MkFolder>
<XRegisterLogsFolder :logs="requestLogs"/>
<component :is="loadingHandler.component.value" v-if="loadingHandler.showing.value"/>
<template v-else>
<div v-if="gridItems.length === 0" style="text-align: center">
{{ i18n.ts._customEmojisManager._local._list.emojisNothing }}
</div>
<template v-else>
<div v-if="gridItems.length > 0" :class="$style.gridArea">
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
</div>
<div :class="$style.footer">
<div>
<!-- レイアウト調整用のスペース -->
</div>
<div :class="$style.center">
<MkPagingButtons :current="currentPage" :max="allPages" :buttonCount="5" @pageChanged="onPageChanged"/>
</div>
<div :class="$style.right">
<MkButton primary @click="onImportClicked">
{{
i18n.ts._customEmojisManager._remote.importEmojisButton
}} ({{ checkedItemsCount }})
</MkButton>
</div>
</div>
</template>
</template>
</div>
</template>
</MkStickyContainer>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, useCssModule } from 'vue';
import * as Misskey from 'misskey-js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue';
import MkGrid from '@/components/grid/MkGrid.vue';
import {
emptyStrToUndefined,
GridSortOrderKey,
gridSortOrderKeys,
RequestLogItem,
} from '@/pages/admin/custom-emojis-manager.impl.js';
import { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
import MkFolder from '@/components/MkFolder.vue';
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
import * as os from '@/os.js';
import { GridSetting } from '@/components/grid/grid.js';
import { deviceKind } from '@/scripts/device-kind.js';
import MkPagingButtons from '@/components/MkPagingButtons.vue';
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
import { useLoading } from "@/components/hook/useLoading.js";
type GridItem = {
checked: boolean;
id: string;
url: string;
name: string;
host: string;
}
function setupGrid(): GridSetting {
const $style = useCssModule();
return {
row: {
// 100
minimumDefinitionCount: 100,
styleRules: [
{
//
condition: ({ row }) => gridItems.value[row.index].checked,
applyStyle: { className: $style.changedRow },
},
],
contextMenuFactory: (row, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._remote.importSelectionRows,
icon: 'ti ti-download',
action: async () => {
const targets = context.rangedRows.map(it => gridItems.value[it.index]);
await importEmojis(targets);
},
},
];
},
},
cols: [
{ bindTo: 'checked', icon: 'ti-download', type: 'boolean', editable: true, width: 34 },
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 'auto' },
{ bindTo: 'host', title: 'host', type: 'text', editable: false, width: 'auto' },
{ bindTo: 'uri', title: 'uri', type: 'text', editable: false, width: 'auto' },
{ bindTo: 'publicUrl', title: 'publicUrl', type: 'text', editable: false, width: 'auto' },
],
cells: {
contextMenuFactory: (col, row, value, context) => {
return [
{
type: 'button',
text: i18n.ts._customEmojisManager._remote.importSelectionRangesRows,
icon: 'ti ti-download',
action: async () => {
const targets = context.rangedCells.map(it => gridItems.value[it.row.index]);
await importEmojis(targets);
},
},
];
},
},
};
}
const loadingHandler = useLoading();
const customEmojis = ref<Misskey.entities.EmojiDetailedAdmin[]>([]);
const allPages = ref<number>(0);
const currentPage = ref<number>(0);
const queryName = ref<string | null>(null);
const queryHost = ref<string | null>(null);
const queryUri = ref<string | null>(null);
const queryPublicUrl = ref<string | null>(null);
const previousQuery = ref<string | undefined>(undefined);
const sortOrders = ref<SortOrder<GridSortOrderKey>[]>([]);
const requestLogs = ref<RequestLogItem[]>([]);
const gridItems = ref<GridItem[]>([]);
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
const checkedItemsCount = computed(() => gridItems.value.filter(it => it.checked).length);
function onSortOrderUpdate(_sortOrders: SortOrder<GridSortOrderKey>[]) {
sortOrders.value = _sortOrders;
}
async function onSearchRequest() {
await refreshCustomEmojis();
}
function onQueryResetButtonClicked() {
queryName.value = null;
queryHost.value = null;
queryUri.value = null;
queryPublicUrl.value = null;
}
async function onPageChanged(pageNumber: number) {
currentPage.value = pageNumber;
await refreshCustomEmojis();
}
async function onImportClicked() {
const targets = gridItems.value.filter(it => it.checked);
await importEmojis(targets);
}
function onGridEvent(event: GridEvent) {
switch (event.type) {
case 'cell-value-change':
onGridCellValueChange(event);
break;
}
}
function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue;
}
}
async function importEmojis(targets: GridItem[]) {
const confirm = await os.confirm({
type: 'info',
title: i18n.ts._customEmojisManager._remote.confirmImportEmojisTitle,
text: i18n.tsx._customEmojisManager._remote.confirmImportEmojisDescription({ count: targets.length }),
});
if (confirm.canceled) {
return;
}
const result = await os.promiseDialog(
Promise.all(
targets.map(item =>
misskeyApi(
'admin/emoji/copy',
{
emojiId: item.id!,
})
.then(() => ({ item, success: true, err: undefined }))
.catch(err => ({ item, success: false, err })),
),
),
);
const failedItems = result.filter(it => !it.success);
if (failedItems.length > 0) {
await os.alert({
type: 'error',
title: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedTitle,
text: i18n.ts._customEmojisManager._gridCommon.alertEmojisRegisterFailedDescription,
});
}
requestLogs.value = result.map(it => ({
failed: !it.success,
url: it.item.url,
name: it.item.name,
error: it.err ? JSON.stringify(it.err) : undefined,
}));
await refreshCustomEmojis();
}
async function refreshCustomEmojis() {
const query: Misskey.entities.V2AdminEmojiListRequest['query'] = {
name: emptyStrToUndefined(queryName.value),
host: emptyStrToUndefined(queryHost.value),
uri: emptyStrToUndefined(queryUri.value),
publicUrl: emptyStrToUndefined(queryPublicUrl.value),
hostType: 'remote',
};
if (JSON.stringify(query) !== previousQuery.value) {
currentPage.value = 1;
}
const result = await loadingHandler.scope(() => misskeyApi('v2/admin/emoji/list', {
limit: 100,
query: query,
page: currentPage.value,
sortKeys: sortOrders.value.map(({ key, direction }) => `${direction}${key}`) as never[],
}));
customEmojis.value = result.emojis;
allPages.value = result.allPages;
previousQuery.value = JSON.stringify(query);
gridItems.value = customEmojis.value.map(it => ({
checked: false,
id: it.id,
url: it.publicUrl,
name: it.name,
host: it.host!,
}));
}
onMounted(async () => {
await refreshCustomEmojis();
});
</script>
<style module lang="scss">
.row1 {
grid-row: 1 / 2;
}
.row2 {
grid-row: 2 / 3;
}
.col1 {
grid-column: 1 / 2;
}
.col2 {
grid-column: 2 / 3;
}
.root {
padding: 16px;
}
.changedRow {
background-color: var(--MI_THEME-infoBg);
}
.searchArea {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.searchButtons {
display: flex;
justify-content: flex-end;
align-items: flex-end;
gap: 8px;
}
.searchButtonsSp {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
.searchAreaSp {
display: flex;
flex-direction: column;
gap: 8px;
}
.gridArea {
padding-top: 8px;
padding-bottom: 8px;
}
.pages {
display: flex;
justify-content: center;
align-items: center;
button {
background-color: var(--MI_THEME-buttonBg);
border-radius: 9999px;
border: none;
margin: 0 4px;
padding: 8px;
}
}
.footer {
background-color: var(--MI_THEME-bg);
position: sticky;
left:0;
bottom:0;
z-index: 1;
// stickypadding
margin-top: calc(var(--MI-margin) * -1);
margin-bottom: calc(var(--MI-margin) * -1);
padding-top: var(--MI-margin);
padding-bottom: var(--MI-margin);
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
& .center {
display: flex;
justify-content: center;
align-items: center;
}
& .right {
display: flex;
justify-content: flex-end;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,160 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { delay, http, HttpResponse } from 'msw';
import { StoryObj } from '@storybook/vue3';
import { entities } from 'misskey-js';
import { commonHandlers } from '../../../.storybook/mocks.js';
import { emoji } from '../../../.storybook/fakes.js';
import { fakeId } from '../../../.storybook/fake-utils.js';
import custom_emojis_manager2 from './custom-emojis-manager2.vue';
function createRender(params: {
emojis: entities.EmojiDetailedAdmin[];
}) {
const storedEmojis: entities.EmojiDetailedAdmin[] = [...params.emojis];
const storedDriveFiles: entities.DriveFile[] = [];
return {
render(args) {
return {
components: {
custom_emojis_manager2,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<custom_emojis_manager2 v-bind="props" />',
};
},
args: {
},
parameters: {
layout: 'fullscreen',
msw: {
handlers: [
...commonHandlers,
http.post('/api/v2/admin/emoji/list', async ({ request }) => {
await delay(100);
const bodyStream = request.body as ReadableStream;
const body = await new Response(bodyStream).json() as entities.V2AdminEmojiListRequest;
const emojis = storedEmojis;
const limit = body.limit ?? 10;
const page = body.page ?? 1;
const result = emojis.slice((page - 1) * limit, page * limit);
return HttpResponse.json({
emojis: result,
count: Math.min(emojis.length, limit),
allCount: emojis.length,
allPages: Math.ceil(emojis.length / limit),
});
}),
http.post('/api/drive/folders', () => {
return HttpResponse.json([]);
}),
http.post('/api/drive/files', () => {
return HttpResponse.json(storedDriveFiles);
}),
http.post('/api/drive/files/create', async ({ request }) => {
const data = await request.formData();
const file = data.get('file');
if (!file || !(file instanceof File)) {
return HttpResponse.json({ error: 'file is required' }, {
status: 400,
});
}
// FIXME: ファイルのバイナリに0xEF 0xBF 0xBDが混入してしまい、うまく画像ファイルとして表示できない問題がある
const base64 = await new Promise<string>((resolve) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result as string);
};
reader.readAsDataURL(new Blob([file], { type: 'image/webp' }));
});
const driveFile: entities.DriveFile = {
id: fakeId(file.name),
createdAt: new Date().toISOString(),
name: file.name,
type: file.type,
md5: '',
size: file.size,
isSensitive: false,
blurhash: null,
properties: {},
url: base64,
thumbnailUrl: null,
comment: null,
folderId: null,
folder: null,
userId: null,
user: null,
};
storedDriveFiles.push(driveFile);
return HttpResponse.json(driveFile);
}),
http.post('api/admin/emoji/add', async ({ request }) => {
await delay(100);
const bodyStream = request.body as ReadableStream;
const body = await new Response(bodyStream).json() as entities.AdminEmojiAddRequest;
const fileId = body.fileId;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const file = storedDriveFiles.find(f => f.id === fileId)!;
const em = emoji({
id: fakeId(file.name),
name: body.name,
publicUrl: file.url,
originalUrl: file.url,
type: file.type,
aliases: body.aliases,
category: body.category ?? undefined,
license: body.license ?? undefined,
localOnly: body.localOnly,
isSensitive: body.isSensitive,
});
storedEmojis.push(em);
return HttpResponse.json(null);
}),
],
},
},
} satisfies StoryObj<typeof custom_emojis_manager2>;
}
export const Default = createRender({
emojis: [],
});
export const List10 = createRender({
emojis: Array.from({ length: 10 }, (_, i) => emoji({ name: `emoji_${i}` }, i.toString())),
});
export const List100 = createRender({
emojis: Array.from({ length: 100 }, (_, i) => emoji({ name: `emoji_${i}` }, i.toString())),
});
export const List1000 = createRender({
emojis: Array.from({ length: 1000 }, (_, i) => emoji({ name: `emoji_${i}` }, i.toString())),
});

View File

@ -0,0 +1,44 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div>
<!-- コンテナが入れ子になるのでz-indexが被らないよう大きめの数値を設定する-->
<MkStickyContainer :headerZIndex="2000">
<template #header>
<MkPageHeader v-model:tab="headerTab" :tabs="headerTabs"/>
</template>
<XGridLocalComponent v-if="headerTab === 'local'"/>
<XGridRemoteComponent v-else/>
</MkStickyContainer>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import XGridLocalComponent from '@/pages/admin/custom-emojis-manager.local.vue';
import XGridRemoteComponent from '@/pages/admin/custom-emojis-manager.remote.vue';
import MkPageHeader from '@/components/global/MkPageHeader.vue';
import MkStickyContainer from '@/components/global/MkStickyContainer.vue';
type PageMode = 'local' | 'remote';
const headerTab = ref<PageMode>('local');
const headerTabs = computed(() => [{
key: 'local',
title: i18n.ts.local,
}, {
key: 'remote',
title: i18n.ts.remote,
}]);
definePageMetadata(computed(() => ({
title: i18n.ts.customEmojis,
icon: 'ti ti-icons',
})));
</script>

View File

@ -121,6 +121,11 @@ const menuDef = computed(() => [{
text: i18n.ts.customEmojis, text: i18n.ts.customEmojis,
to: '/admin/emojis', to: '/admin/emojis',
active: currentPage.value?.route.name === 'emojis', active: currentPage.value?.route.name === 'emojis',
}, {
icon: 'ti ti-icons',
text: i18n.ts.customEmojis + '(beta)',
to: '/admin/emojis2',
active: currentPage.value?.route.name === 'emojis2',
}, { }, {
icon: 'ti ti-sparkles', icon: 'ti ti-sparkles',
text: i18n.ts.avatarDecorations, text: i18n.ts.avatarDecorations,

View File

@ -382,6 +382,10 @@ const routes: RouteDef[] = [{
path: '/emojis', path: '/emojis',
name: 'emojis', name: 'emojis',
component: page(() => import('@/pages/custom-emojis-manager.vue')), component: page(() => import('@/pages/custom-emojis-manager.vue')),
}, {
path: '/emojis2',
name: 'emojis2',
component: page(() => import('@/pages/admin/custom-emojis-manager2.vue')),
}, { }, {
path: '/avatar-decorations', path: '/avatar-decorations',
name: 'avatarDecorations', name: 'avatarDecorations',

View File

@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export type DroppedItem = DroppedFile | DroppedDirectory;
export type DroppedFile = {
isFile: true;
path: string;
file: File;
};
export type DroppedDirectory = {
isFile: false;
path: string;
children: DroppedItem[];
}
export async function extractDroppedItems(ev: DragEvent): Promise<DroppedItem[]> {
const dropItems = ev.dataTransfer?.items;
if (!dropItems || dropItems.length === 0) {
return [];
}
const apiTestItem = dropItems[0];
if ('webkitGetAsEntry' in apiTestItem) {
return readDataTransferItems(dropItems);
} else {
// webkitGetAsEntryに対応していない場合はfilesから取得するディレクトリのサポートは出来ない
const dropFiles = ev.dataTransfer.files;
if (dropFiles.length === 0) {
return [];
}
const droppedFiles = Array.of<DroppedFile>();
for (let i = 0; i < dropFiles.length; i++) {
const file = dropFiles.item(i);
if (file) {
droppedFiles.push({
isFile: true,
path: file.name,
file,
});
}
}
return droppedFiles;
}
}
/**
* {@link File}
*/
export async function readDataTransferItems(itemList: DataTransferItemList): Promise<DroppedItem[]> {
async function readEntry(entry: FileSystemEntry): Promise<DroppedItem> {
if (entry.isFile) {
return {
isFile: true,
path: entry.fullPath,
file: await readFile(entry as FileSystemFileEntry),
};
} else {
return {
isFile: false,
path: entry.fullPath,
children: await readDirectory(entry as FileSystemDirectoryEntry),
};
}
}
function readFile(fileSystemFileEntry: FileSystemFileEntry): Promise<File> {
return new Promise((resolve, reject) => {
fileSystemFileEntry.file(resolve, reject);
});
}
function readDirectory(fileSystemDirectoryEntry: FileSystemDirectoryEntry): Promise<DroppedItem[]> {
return new Promise(async (resolve) => {
const allEntries = Array.of<FileSystemEntry>();
const reader = fileSystemDirectoryEntry.createReader();
while (true) {
const entries = await new Promise<FileSystemEntry[]>((res, rej) => reader.readEntries(res, rej));
if (entries.length === 0) {
break;
}
allEntries.push(...entries);
}
resolve(await Promise.all(allEntries.map(readEntry)));
});
}
// 扱いにくいので配列に変換
const items = Array.of<DataTransferItem>();
for (let i = 0; i < itemList.length; i++) {
items.push(itemList[i]);
}
return Promise.all(
items
.map(it => it.webkitGetAsEntry())
.filter(it => it)
.map(it => readEntry(it!)),
);
}
/**
* {@link DroppedItem}
*/
export function flattenDroppedFiles(items: DroppedItem[]): DroppedFile[] {
const result = Array.of<DroppedFile>();
for (const item of items) {
if (item.isFile) {
result.push(item);
} else {
result.push(...flattenDroppedFiles(item.children));
}
}
return result;
}

View File

@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/**
* {@link KeyboardEvent.code}
* @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
*/
export type KeyCode =
| 'Backspace'
| 'Tab'
| 'Enter'
| 'Shift'
| 'Control'
| 'Alt'
| 'Pause'
| 'CapsLock'
| 'Escape'
| 'Space'
| 'PageUp'
| 'PageDown'
| 'End'
| 'Home'
| 'ArrowLeft'
| 'ArrowUp'
| 'ArrowRight'
| 'ArrowDown'
| 'Insert'
| 'Delete'
| 'Digit0'
| 'Digit1'
| 'Digit2'
| 'Digit3'
| 'Digit4'
| 'Digit5'
| 'Digit6'
| 'Digit7'
| 'Digit8'
| 'Digit9'
| 'KeyA'
| 'KeyB'
| 'KeyC'
| 'KeyD'
| 'KeyE'
| 'KeyF'
| 'KeyG'
| 'KeyH'
| 'KeyI'
| 'KeyJ'
| 'KeyK'
| 'KeyL'
| 'KeyM'
| 'KeyN'
| 'KeyO'
| 'KeyP'
| 'KeyQ'
| 'KeyR'
| 'KeyS'
| 'KeyT'
| 'KeyU'
| 'KeyV'
| 'KeyW'
| 'KeyX'
| 'KeyY'
| 'KeyZ'
| 'MetaLeft'
| 'MetaRight'
| 'ContextMenu'
| 'F1'
| 'F2'
| 'F3'
| 'F4'
| 'F5'
| 'F6'
| 'F7'
| 'F8'
| 'F9'
| 'F10'
| 'F11'
| 'F12'
| 'NumLock'
| 'ScrollLock'
| 'Semicolon'
| 'Equal'
| 'Comma'
| 'Minus'
| 'Period'
| 'Slash'
| 'Backquote'
| 'BracketLeft'
| 'Backslash'
| 'BracketRight'
| 'Quote'
| 'Meta'
| 'AltGraph'
;
/**
*
*/
export type KeyModifier =
| 'Shift'
| 'Control'
| 'Alt'
| 'Meta'
;
/**
*
*/
export type KeyState =
| 'composing'
| 'repeat'
;
export type KeyEventHandler = {
modifiers?: KeyModifier[];
states?: KeyState[];
code: KeyCode | 'any';
handler: (event: KeyboardEvent) => void;
}
export function handleKeyEvent(event: KeyboardEvent, handlers: KeyEventHandler[]) {
function checkModifier(ev: KeyboardEvent, modifiers? : KeyModifier[]) {
if (modifiers) {
return modifiers.every(modifier => ev.getModifierState(modifier));
}
return true;
}
function checkState(ev: KeyboardEvent, states?: KeyState[]) {
if (states) {
return states.every(state => ev.getModifierState(state));
}
return true;
}
let hit = false;
for (const handler of handlers.filter(it => it.code === event.code)) {
if (checkModifier(event, handler.modifiers) && checkState(event, handler.states)) {
handler.handler(event);
hit = true;
break;
}
}
if (!hit) {
for (const handler of handlers.filter(it => it.code === 'any')) {
handler.handler(event);
}
}
}

View File

@ -12,14 +12,28 @@ import { i18n } from '@/i18n.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { uploadFile } from '@/scripts/upload.js'; import { uploadFile } from '@/scripts/upload.js';
export function chooseFileFromPc(multiple: boolean, keepOriginal = false): Promise<Misskey.entities.DriveFile[]> { export function chooseFileFromPc(
multiple: boolean,
options?: {
uploadFolder?: string | null;
keepOriginal?: boolean;
nameConverter?: (file: File) => string | undefined;
},
): Promise<Misskey.entities.DriveFile[]> {
const uploadFolder = options?.uploadFolder ?? defaultStore.state.uploadFolder;
const keepOriginal = options?.keepOriginal ?? defaultStore.state.keepOriginalUploading;
const nameConverter = options?.nameConverter ?? (() => undefined);
return new Promise((res, rej) => { return new Promise((res, rej) => {
const input = document.createElement('input'); const input = document.createElement('input');
input.type = 'file'; input.type = 'file';
input.multiple = multiple; input.multiple = multiple;
input.onchange = () => { input.onchange = () => {
if (!input.files) return res([]); if (!input.files) return res([]);
const promises = Array.from(input.files, file => uploadFile(file, defaultStore.state.uploadFolder, undefined, keepOriginal)); const promises = Array.from(
input.files,
file => uploadFile(file, uploadFolder, nameConverter(file), keepOriginal),
);
Promise.all(promises).then(driveFiles => { Promise.all(promises).then(driveFiles => {
res(driveFiles); res(driveFiles);
@ -94,7 +108,7 @@ function select(src: HTMLElement | EventTarget | null, label: string | null, mul
}, { }, {
text: i18n.ts.upload, text: i18n.ts.upload,
icon: 'ti ti-upload', icon: 'ti ti-upload',
action: () => chooseFileFromPc(multiple, keepOriginal.value).then(files => res(files)), action: () => chooseFileFromPc(multiple, { keepOriginal: keepOriginal.value }).then(files => res(files)),
}, { }, {
text: i18n.ts.fromDrive, text: i18n.ts.fromDrive,
icon: 'ti ti-cloud', icon: 'ti ti-cloud',

View File

@ -1117,6 +1117,9 @@ type EmojiDeleted = {
// @public (undocumented) // @public (undocumented)
type EmojiDetailed = components['schemas']['EmojiDetailed']; type EmojiDetailed = components['schemas']['EmojiDetailed'];
// @public (undocumented)
type EmojiDetailedAdmin = components['schemas']['EmojiDetailedAdmin'];
// @public (undocumented) // @public (undocumented)
type EmojiRequest = operations['emoji']['requestBody']['content']['application/json']; type EmojiRequest = operations['emoji']['requestBody']['content']['application/json'];
@ -1233,18 +1236,17 @@ declare namespace entities {
PartialRolePolicyOverride, PartialRolePolicyOverride,
EmptyRequest, EmptyRequest,
EmptyResponse, EmptyResponse,
AdminMetaResponse, AdminAbuseReportNotificationRecipientCreateRequest,
AdminAbuseUserReportsRequest, AdminAbuseReportNotificationRecipientCreateResponse,
AdminAbuseUserReportsResponse, AdminAbuseReportNotificationRecipientDeleteRequest,
AdminAbuseReportNotificationRecipientListRequest, AdminAbuseReportNotificationRecipientListRequest,
AdminAbuseReportNotificationRecipientListResponse, AdminAbuseReportNotificationRecipientListResponse,
AdminAbuseReportNotificationRecipientShowRequest, AdminAbuseReportNotificationRecipientShowRequest,
AdminAbuseReportNotificationRecipientShowResponse, AdminAbuseReportNotificationRecipientShowResponse,
AdminAbuseReportNotificationRecipientCreateRequest,
AdminAbuseReportNotificationRecipientCreateResponse,
AdminAbuseReportNotificationRecipientUpdateRequest, AdminAbuseReportNotificationRecipientUpdateRequest,
AdminAbuseReportNotificationRecipientUpdateResponse, AdminAbuseReportNotificationRecipientUpdateResponse,
AdminAbuseReportNotificationRecipientDeleteRequest, AdminAbuseUserReportsRequest,
AdminAbuseUserReportsResponse,
AdminAccountsCreateRequest, AdminAccountsCreateRequest,
AdminAccountsCreateResponse, AdminAccountsCreateResponse,
AdminAccountsDeleteRequest, AdminAccountsDeleteRequest,
@ -1270,25 +1272,24 @@ declare namespace entities {
AdminAvatarDecorationsUpdateRequest, AdminAvatarDecorationsUpdateRequest,
AdminCaptchaCurrentResponse, AdminCaptchaCurrentResponse,
AdminCaptchaSaveRequest, AdminCaptchaSaveRequest,
AdminDeleteAccountRequest,
AdminDeleteAllFilesOfAUserRequest, AdminDeleteAllFilesOfAUserRequest,
AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
AdminDriveFilesRequest, AdminDriveFilesRequest,
AdminDriveFilesResponse, AdminDriveFilesResponse,
AdminDriveShowFileRequest, AdminDriveShowFileRequest,
AdminDriveShowFileResponse, AdminDriveShowFileResponse,
AdminEmojiAddAliasesBulkRequest,
AdminEmojiAddRequest, AdminEmojiAddRequest,
AdminEmojiAddResponse, AdminEmojiAddResponse,
AdminEmojiAddAliasesBulkRequest,
AdminEmojiCopyRequest, AdminEmojiCopyRequest,
AdminEmojiCopyResponse, AdminEmojiCopyResponse,
AdminEmojiDeleteBulkRequest,
AdminEmojiDeleteRequest, AdminEmojiDeleteRequest,
AdminEmojiDeleteBulkRequest,
AdminEmojiImportZipRequest, AdminEmojiImportZipRequest,
AdminEmojiListRemoteRequest,
AdminEmojiListRemoteResponse,
AdminEmojiListRequest, AdminEmojiListRequest,
AdminEmojiListResponse, AdminEmojiListResponse,
AdminEmojiListRemoteRequest,
AdminEmojiListRemoteResponse,
AdminEmojiRemoveAliasesBulkRequest, AdminEmojiRemoveAliasesBulkRequest,
AdminEmojiSetAliasesBulkRequest, AdminEmojiSetAliasesBulkRequest,
AdminEmojiSetCategoryBulkRequest, AdminEmojiSetCategoryBulkRequest,
@ -1298,6 +1299,7 @@ declare namespace entities {
AdminFederationRefreshRemoteInstanceMetadataRequest, AdminFederationRefreshRemoteInstanceMetadataRequest,
AdminFederationRemoveAllFollowingRequest, AdminFederationRemoveAllFollowingRequest,
AdminFederationUpdateInstanceRequest, AdminFederationUpdateInstanceRequest,
AdminForwardAbuseUserReportRequest,
AdminGetIndexStatsResponse, AdminGetIndexStatsResponse,
AdminGetTableStatsResponse, AdminGetTableStatsResponse,
AdminGetUserIpsRequest, AdminGetUserIpsRequest,
@ -1306,6 +1308,7 @@ declare namespace entities {
AdminInviteCreateResponse, AdminInviteCreateResponse,
AdminInviteListRequest, AdminInviteListRequest,
AdminInviteListResponse, AdminInviteListResponse,
AdminMetaResponse,
AdminPromoCreateRequest, AdminPromoCreateRequest,
AdminQueueDeliverDelayedResponse, AdminQueueDeliverDelayedResponse,
AdminQueueInboxDelayedResponse, AdminQueueInboxDelayedResponse,
@ -1318,8 +1321,18 @@ declare namespace entities {
AdminResetPasswordRequest, AdminResetPasswordRequest,
AdminResetPasswordResponse, AdminResetPasswordResponse,
AdminResolveAbuseUserReportRequest, AdminResolveAbuseUserReportRequest,
AdminForwardAbuseUserReportRequest, AdminRolesAssignRequest,
AdminUpdateAbuseUserReportRequest, AdminRolesCreateRequest,
AdminRolesCreateResponse,
AdminRolesDeleteRequest,
AdminRolesListResponse,
AdminRolesShowRequest,
AdminRolesShowResponse,
AdminRolesUnassignRequest,
AdminRolesUpdateRequest,
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSendEmailRequest, AdminSendEmailRequest,
AdminServerInfoResponse, AdminServerInfoResponse,
AdminShowModerationLogsRequest, AdminShowModerationLogsRequest,
@ -1329,22 +1342,6 @@ declare namespace entities {
AdminShowUsersRequest, AdminShowUsersRequest,
AdminShowUsersResponse, AdminShowUsersResponse,
AdminSuspendUserRequest, AdminSuspendUserRequest,
AdminUnsuspendUserRequest,
AdminUpdateMetaRequest,
AdminDeleteAccountRequest,
AdminUpdateUserNoteRequest,
AdminRolesCreateRequest,
AdminRolesCreateResponse,
AdminRolesDeleteRequest,
AdminRolesListResponse,
AdminRolesShowRequest,
AdminRolesShowResponse,
AdminRolesUpdateRequest,
AdminRolesAssignRequest,
AdminRolesUnassignRequest,
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSystemWebhookCreateRequest, AdminSystemWebhookCreateRequest,
AdminSystemWebhookCreateResponse, AdminSystemWebhookCreateResponse,
AdminSystemWebhookDeleteRequest, AdminSystemWebhookDeleteRequest,
@ -1352,9 +1349,15 @@ declare namespace entities {
AdminSystemWebhookListResponse, AdminSystemWebhookListResponse,
AdminSystemWebhookShowRequest, AdminSystemWebhookShowRequest,
AdminSystemWebhookShowResponse, AdminSystemWebhookShowResponse,
AdminSystemWebhookTestRequest,
AdminSystemWebhookUpdateRequest, AdminSystemWebhookUpdateRequest,
AdminSystemWebhookUpdateResponse, AdminSystemWebhookUpdateResponse,
AdminSystemWebhookTestRequest, AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
AdminUnsuspendUserRequest,
AdminUpdateAbuseUserReportRequest,
AdminUpdateMetaRequest,
AdminUpdateUserNoteRequest,
AnnouncementsRequest, AnnouncementsRequest,
AnnouncementsResponse, AnnouncementsResponse,
AnnouncementsShowRequest, AnnouncementsShowRequest,
@ -1390,26 +1393,29 @@ declare namespace entities {
BlockingDeleteResponse, BlockingDeleteResponse,
BlockingListRequest, BlockingListRequest,
BlockingListResponse, BlockingListResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
BubbleGameRegisterRequest,
ChannelsCreateRequest, ChannelsCreateRequest,
ChannelsCreateResponse, ChannelsCreateResponse,
ChannelsFavoriteRequest,
ChannelsFeaturedResponse, ChannelsFeaturedResponse,
ChannelsFollowRequest, ChannelsFollowRequest,
ChannelsFollowedRequest, ChannelsFollowedRequest,
ChannelsFollowedResponse, ChannelsFollowedResponse,
ChannelsMyFavoritesResponse,
ChannelsOwnedRequest, ChannelsOwnedRequest,
ChannelsOwnedResponse, ChannelsOwnedResponse,
ChannelsSearchRequest,
ChannelsSearchResponse,
ChannelsShowRequest, ChannelsShowRequest,
ChannelsShowResponse, ChannelsShowResponse,
ChannelsTimelineRequest, ChannelsTimelineRequest,
ChannelsTimelineResponse, ChannelsTimelineResponse,
ChannelsUnfavoriteRequest,
ChannelsUnfollowRequest, ChannelsUnfollowRequest,
ChannelsUpdateRequest, ChannelsUpdateRequest,
ChannelsUpdateResponse, ChannelsUpdateResponse,
ChannelsFavoriteRequest,
ChannelsUnfavoriteRequest,
ChannelsMyFavoritesResponse,
ChannelsSearchRequest,
ChannelsSearchResponse,
ChartsActiveUsersRequest, ChartsActiveUsersRequest,
ChartsActiveUsersResponse, ChartsActiveUsersResponse,
ChartsApRequestRequest, ChartsApRequestRequest,
@ -1435,20 +1441,20 @@ declare namespace entities {
ChartsUsersRequest, ChartsUsersRequest,
ChartsUsersResponse, ChartsUsersResponse,
ClipsAddNoteRequest, ClipsAddNoteRequest,
ClipsRemoveNoteRequest,
ClipsCreateRequest, ClipsCreateRequest,
ClipsCreateResponse, ClipsCreateResponse,
ClipsDeleteRequest, ClipsDeleteRequest,
ClipsFavoriteRequest,
ClipsListResponse, ClipsListResponse,
ClipsMyFavoritesResponse,
ClipsNotesRequest, ClipsNotesRequest,
ClipsNotesResponse, ClipsNotesResponse,
ClipsRemoveNoteRequest,
ClipsShowRequest, ClipsShowRequest,
ClipsShowResponse, ClipsShowResponse,
ClipsUnfavoriteRequest,
ClipsUpdateRequest, ClipsUpdateRequest,
ClipsUpdateResponse, ClipsUpdateResponse,
ClipsFavoriteRequest,
ClipsUnfavoriteRequest,
ClipsMyFavoritesResponse,
DriveResponse, DriveResponse,
DriveFilesRequest, DriveFilesRequest,
DriveFilesResponse, DriveFilesResponse,
@ -1459,10 +1465,10 @@ declare namespace entities {
DriveFilesCreateRequest, DriveFilesCreateRequest,
DriveFilesCreateResponse, DriveFilesCreateResponse,
DriveFilesDeleteRequest, DriveFilesDeleteRequest,
DriveFilesFindByHashRequest,
DriveFilesFindByHashResponse,
DriveFilesFindRequest, DriveFilesFindRequest,
DriveFilesFindResponse, DriveFilesFindResponse,
DriveFilesFindByHashRequest,
DriveFilesFindByHashResponse,
DriveFilesShowRequest, DriveFilesShowRequest,
DriveFilesShowResponse, DriveFilesShowResponse,
DriveFilesUpdateRequest, DriveFilesUpdateRequest,
@ -1483,6 +1489,9 @@ declare namespace entities {
DriveStreamResponse, DriveStreamResponse,
EmailAddressAvailableRequest, EmailAddressAvailableRequest,
EmailAddressAvailableResponse, EmailAddressAvailableResponse,
EmojiRequest,
EmojiResponse,
EmojisResponse,
EndpointRequest, EndpointRequest,
EndpointResponse, EndpointResponse,
EndpointsResponse, EndpointsResponse,
@ -1494,18 +1503,33 @@ declare namespace entities {
FederationInstancesResponse, FederationInstancesResponse,
FederationShowInstanceRequest, FederationShowInstanceRequest,
FederationShowInstanceResponse, FederationShowInstanceResponse,
FederationStatsRequest,
FederationStatsResponse,
FederationUpdateRemoteUserRequest, FederationUpdateRemoteUserRequest,
FederationUsersRequest, FederationUsersRequest,
FederationUsersResponse, FederationUsersResponse,
FederationStatsRequest, FetchExternalResourcesRequest,
FederationStatsResponse, FetchExternalResourcesResponse,
FetchRssRequest,
FetchRssResponse,
FlashCreateRequest,
FlashCreateResponse,
FlashDeleteRequest,
FlashFeaturedRequest,
FlashFeaturedResponse,
FlashLikeRequest,
FlashMyRequest,
FlashMyResponse,
FlashMyLikesRequest,
FlashMyLikesResponse,
FlashShowRequest,
FlashShowResponse,
FlashUnlikeRequest,
FlashUpdateRequest,
FollowingCreateRequest, FollowingCreateRequest,
FollowingCreateResponse, FollowingCreateResponse,
FollowingDeleteRequest, FollowingDeleteRequest,
FollowingDeleteResponse, FollowingDeleteResponse,
FollowingUpdateRequest,
FollowingUpdateResponse,
FollowingUpdateAllRequest,
FollowingInvalidateRequest, FollowingInvalidateRequest,
FollowingInvalidateResponse, FollowingInvalidateResponse,
FollowingRequestsAcceptRequest, FollowingRequestsAcceptRequest,
@ -1513,9 +1537,12 @@ declare namespace entities {
FollowingRequestsCancelResponse, FollowingRequestsCancelResponse,
FollowingRequestsListRequest, FollowingRequestsListRequest,
FollowingRequestsListResponse, FollowingRequestsListResponse,
FollowingRequestsRejectRequest,
FollowingRequestsSentRequest, FollowingRequestsSentRequest,
FollowingRequestsSentResponse, FollowingRequestsSentResponse,
FollowingRequestsRejectRequest, FollowingUpdateRequest,
FollowingUpdateResponse,
FollowingUpdateAllRequest,
GalleryFeaturedRequest, GalleryFeaturedRequest,
GalleryFeaturedResponse, GalleryFeaturedResponse,
GalleryPopularResponse, GalleryPopularResponse,
@ -1530,8 +1557,8 @@ declare namespace entities {
GalleryPostsUnlikeRequest, GalleryPostsUnlikeRequest,
GalleryPostsUpdateRequest, GalleryPostsUpdateRequest,
GalleryPostsUpdateResponse, GalleryPostsUpdateResponse,
GetOnlineUsersCountResponse,
GetAvatarDecorationsResponse, GetAvatarDecorationsResponse,
GetOnlineUsersCountResponse,
HashtagsListRequest, HashtagsListRequest,
HashtagsListResponse, HashtagsListResponse,
HashtagsSearchRequest, HashtagsSearchRequest,
@ -1547,19 +1574,19 @@ declare namespace entities {
I2faKeyDoneRequest, I2faKeyDoneRequest,
I2faKeyDoneResponse, I2faKeyDoneResponse,
I2faPasswordLessRequest, I2faPasswordLessRequest,
I2faRegisterKeyRequest,
I2faRegisterKeyResponse,
I2faRegisterRequest, I2faRegisterRequest,
I2faRegisterResponse, I2faRegisterResponse,
I2faUpdateKeyRequest, I2faRegisterKeyRequest,
I2faRegisterKeyResponse,
I2faRemoveKeyRequest, I2faRemoveKeyRequest,
I2faUnregisterRequest, I2faUnregisterRequest,
I2faUpdateKeyRequest,
IAppsRequest, IAppsRequest,
IAppsResponse, IAppsResponse,
IAuthorizedAppsRequest, IAuthorizedAppsRequest,
IAuthorizedAppsResponse, IAuthorizedAppsResponse,
IClaimAchievementRequest,
IChangePasswordRequest, IChangePasswordRequest,
IClaimAchievementRequest,
IDeleteAccountRequest, IDeleteAccountRequest,
IExportFollowingRequest, IExportFollowingRequest,
IFavoritesRequest, IFavoritesRequest,
@ -1568,11 +1595,13 @@ declare namespace entities {
IGalleryLikesResponse, IGalleryLikesResponse,
IGalleryPostsRequest, IGalleryPostsRequest,
IGalleryPostsResponse, IGalleryPostsResponse,
IImportAntennasRequest,
IImportBlockingRequest, IImportBlockingRequest,
IImportFollowingRequest, IImportFollowingRequest,
IImportMutingRequest, IImportMutingRequest,
IImportUserListsRequest, IImportUserListsRequest,
IImportAntennasRequest, IMoveRequest,
IMoveResponse,
INotificationsRequest, INotificationsRequest,
INotificationsResponse, INotificationsResponse,
INotificationsGroupedRequest, INotificationsGroupedRequest,
@ -1585,16 +1614,16 @@ declare namespace entities {
IPinResponse, IPinResponse,
IReadAnnouncementRequest, IReadAnnouncementRequest,
IRegenerateTokenRequest, IRegenerateTokenRequest,
IRegistryGetRequest,
IRegistryGetResponse,
IRegistryGetAllRequest, IRegistryGetAllRequest,
IRegistryGetAllResponse, IRegistryGetAllResponse,
IRegistryGetDetailRequest, IRegistryGetDetailRequest,
IRegistryGetDetailResponse, IRegistryGetDetailResponse,
IRegistryGetRequest,
IRegistryGetResponse,
IRegistryKeysWithTypeRequest,
IRegistryKeysWithTypeResponse,
IRegistryKeysRequest, IRegistryKeysRequest,
IRegistryKeysResponse, IRegistryKeysResponse,
IRegistryKeysWithTypeRequest,
IRegistryKeysWithTypeResponse,
IRegistryRemoveRequest, IRegistryRemoveRequest,
IRegistryScopesWithDomainResponse, IRegistryScopesWithDomainResponse,
IRegistrySetRequest, IRegistrySetRequest,
@ -1603,40 +1632,31 @@ declare namespace entities {
ISigninHistoryResponse, ISigninHistoryResponse,
IUnpinRequest, IUnpinRequest,
IUnpinResponse, IUnpinResponse,
IUpdateEmailRequest,
IUpdateEmailResponse,
IUpdateRequest, IUpdateRequest,
IUpdateResponse, IUpdateResponse,
IMoveRequest, IUpdateEmailRequest,
IMoveResponse, IUpdateEmailResponse,
IWebhooksCreateRequest, IWebhooksCreateRequest,
IWebhooksCreateResponse, IWebhooksCreateResponse,
IWebhooksDeleteRequest,
IWebhooksListResponse, IWebhooksListResponse,
IWebhooksShowRequest, IWebhooksShowRequest,
IWebhooksShowResponse, IWebhooksShowResponse,
IWebhooksUpdateRequest,
IWebhooksDeleteRequest,
IWebhooksTestRequest, IWebhooksTestRequest,
IWebhooksUpdateRequest,
InviteCreateResponse, InviteCreateResponse,
InviteDeleteRequest, InviteDeleteRequest,
InviteLimitResponse,
InviteListRequest, InviteListRequest,
InviteListResponse, InviteListResponse,
InviteLimitResponse,
MetaRequest, MetaRequest,
MetaResponse, MetaResponse,
EmojisResponse,
EmojiRequest,
EmojiResponse,
MiauthGenTokenRequest, MiauthGenTokenRequest,
MiauthGenTokenResponse, MiauthGenTokenResponse,
MuteCreateRequest, MuteCreateRequest,
MuteDeleteRequest, MuteDeleteRequest,
MuteListRequest, MuteListRequest,
MuteListResponse, MuteListResponse,
RenoteMuteCreateRequest,
RenoteMuteDeleteRequest,
RenoteMuteListRequest,
RenoteMuteListResponse,
MyAppsRequest, MyAppsRequest,
MyAppsResponse, MyAppsResponse,
NotesRequest, NotesRequest,
@ -1673,10 +1693,10 @@ declare namespace entities {
NotesRenotesResponse, NotesRenotesResponse,
NotesRepliesRequest, NotesRepliesRequest,
NotesRepliesResponse, NotesRepliesResponse,
NotesSearchByTagRequest,
NotesSearchByTagResponse,
NotesSearchRequest, NotesSearchRequest,
NotesSearchResponse, NotesSearchResponse,
NotesSearchByTagRequest,
NotesSearchByTagResponse,
NotesShowRequest, NotesShowRequest,
NotesShowResponse, NotesShowResponse,
NotesStateRequest, NotesStateRequest,
@ -1701,49 +1721,57 @@ declare namespace entities {
PagesShowResponse, PagesShowResponse,
PagesUnlikeRequest, PagesUnlikeRequest,
PagesUpdateRequest, PagesUpdateRequest,
FlashCreateRequest,
FlashCreateResponse,
FlashDeleteRequest,
FlashFeaturedRequest,
FlashFeaturedResponse,
FlashLikeRequest,
FlashShowRequest,
FlashShowResponse,
FlashUnlikeRequest,
FlashUpdateRequest,
FlashMyRequest,
FlashMyResponse,
FlashMyLikesRequest,
FlashMyLikesResponse,
PingResponse, PingResponse,
PinnedUsersResponse, PinnedUsersResponse,
PromoReadRequest, PromoReadRequest,
RenoteMuteCreateRequest,
RenoteMuteDeleteRequest,
RenoteMuteListRequest,
RenoteMuteListResponse,
RequestResetPasswordRequest,
ResetPasswordRequest,
RetentionResponse,
ReversiCancelMatchRequest,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiInvitationsResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
ReversiVerifyRequest,
ReversiVerifyResponse,
RolesListResponse, RolesListResponse,
RolesNotesRequest,
RolesNotesResponse,
RolesShowRequest, RolesShowRequest,
RolesShowResponse, RolesShowResponse,
RolesUsersRequest, RolesUsersRequest,
RolesUsersResponse, RolesUsersResponse,
RolesNotesRequest,
RolesNotesResponse,
RequestResetPasswordRequest,
ResetPasswordRequest,
ServerInfoResponse, ServerInfoResponse,
StatsResponse, StatsResponse,
SwShowRegistrationRequest,
SwShowRegistrationResponse,
SwUpdateRegistrationRequest,
SwUpdateRegistrationResponse,
SwRegisterRequest, SwRegisterRequest,
SwRegisterResponse, SwRegisterResponse,
SwShowRegistrationRequest,
SwShowRegistrationResponse,
SwUnregisterRequest, SwUnregisterRequest,
SwUpdateRegistrationRequest,
SwUpdateRegistrationResponse,
TestRequest, TestRequest,
TestResponse, TestResponse,
UsernameAvailableRequest, UsernameAvailableRequest,
UsernameAvailableResponse, UsernameAvailableResponse,
UsersRequest, UsersRequest,
UsersResponse, UsersResponse,
UsersAchievementsRequest,
UsersAchievementsResponse,
UsersClipsRequest, UsersClipsRequest,
UsersClipsResponse, UsersClipsResponse,
UsersFeaturedNotesRequest,
UsersFeaturedNotesResponse,
UsersFlashsRequest,
UsersFlashsResponse,
UsersFollowersRequest, UsersFollowersRequest,
UsersFollowersResponse, UsersFollowersResponse,
UsersFollowingRequest, UsersFollowingRequest,
@ -1752,32 +1780,28 @@ declare namespace entities {
UsersGalleryPostsResponse, UsersGalleryPostsResponse,
UsersGetFrequentlyRepliedUsersRequest, UsersGetFrequentlyRepliedUsersRequest,
UsersGetFrequentlyRepliedUsersResponse, UsersGetFrequentlyRepliedUsersResponse,
UsersFeaturedNotesRequest,
UsersFeaturedNotesResponse,
UsersListsCreateRequest, UsersListsCreateRequest,
UsersListsCreateResponse, UsersListsCreateResponse,
UsersListsCreateFromPublicRequest,
UsersListsCreateFromPublicResponse,
UsersListsDeleteRequest, UsersListsDeleteRequest,
UsersListsFavoriteRequest,
UsersListsGetMembershipsRequest,
UsersListsGetMembershipsResponse,
UsersListsListRequest, UsersListsListRequest,
UsersListsListResponse, UsersListsListResponse,
UsersListsPullRequest, UsersListsPullRequest,
UsersListsPushRequest, UsersListsPushRequest,
UsersListsShowRequest, UsersListsShowRequest,
UsersListsShowResponse, UsersListsShowResponse,
UsersListsFavoriteRequest,
UsersListsUnfavoriteRequest, UsersListsUnfavoriteRequest,
UsersListsUpdateRequest, UsersListsUpdateRequest,
UsersListsUpdateResponse, UsersListsUpdateResponse,
UsersListsCreateFromPublicRequest,
UsersListsCreateFromPublicResponse,
UsersListsUpdateMembershipRequest, UsersListsUpdateMembershipRequest,
UsersListsGetMembershipsRequest,
UsersListsGetMembershipsResponse,
UsersNotesRequest, UsersNotesRequest,
UsersNotesResponse, UsersNotesResponse,
UsersPagesRequest, UsersPagesRequest,
UsersPagesResponse, UsersPagesResponse,
UsersFlashsRequest,
UsersFlashsResponse,
UsersReactionsRequest, UsersReactionsRequest,
UsersReactionsResponse, UsersReactionsResponse,
UsersRecommendationRequest, UsersRecommendationRequest,
@ -1785,34 +1809,15 @@ declare namespace entities {
UsersRelationRequest, UsersRelationRequest,
UsersRelationResponse, UsersRelationResponse,
UsersReportAbuseRequest, UsersReportAbuseRequest,
UsersSearchByUsernameAndHostRequest,
UsersSearchByUsernameAndHostResponse,
UsersSearchRequest, UsersSearchRequest,
UsersSearchResponse, UsersSearchResponse,
UsersSearchByUsernameAndHostRequest,
UsersSearchByUsernameAndHostResponse,
UsersShowRequest, UsersShowRequest,
UsersShowResponse, UsersShowResponse,
UsersAchievementsRequest,
UsersAchievementsResponse,
UsersUpdateMemoRequest, UsersUpdateMemoRequest,
FetchRssRequest, V2AdminEmojiListRequest,
FetchRssResponse, V2AdminEmojiListResponse,
FetchExternalResourcesRequest,
FetchExternalResourcesResponse,
RetentionResponse,
BubbleGameRegisterRequest,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchRequest,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
ReversiVerifyRequest,
ReversiVerifyResponse,
Error_2 as Error, Error_2 as Error,
UserLite, UserLite,
UserDetailedNotMeOnly, UserDetailedNotMeOnly,
@ -1847,6 +1852,7 @@ declare namespace entities {
GalleryPost, GalleryPost,
EmojiSimple, EmojiSimple,
EmojiDetailed, EmojiDetailed,
EmojiDetailedAdmin,
Flash, Flash,
Signin, Signin,
RoleCondFormulaLogics, RoleCondFormulaLogics,
@ -3420,6 +3426,12 @@ type UsersShowResponse = operations['users___show']['responses']['200']['content
// @public (undocumented) // @public (undocumented)
type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json']; type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json'];
// @public (undocumented)
type V2AdminEmojiListRequest = operations['v2___admin___emoji___list']['requestBody']['content']['application/json'];
// @public (undocumented)
type V2AdminEmojiListResponse = operations['v2___admin___emoji___list']['responses']['200']['content']['application/json'];
// Warnings were encountered during analysis: // Warnings were encountered during analysis:
// //
// src/entities.ts:50:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/entities.ts:50:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts

View File

@ -1,7 +1,7 @@
{ {
"type": "module", "type": "module",
"name": "misskey-js", "name": "misskey-js",
"version": "2025.1.0-beta.1", "version": "2025.1.0-beta.2",
"description": "Misskey SDK for JavaScript", "description": "Misskey SDK for JavaScript",
"license": "MIT", "license": "MIT",
"main": "./built/index.js", "main": "./built/index.js",

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,17 @@
import type { import type {
EmptyRequest, EmptyRequest,
EmptyResponse, EmptyResponse,
AdminMetaResponse, AdminAbuseReportNotificationRecipientCreateRequest,
AdminAbuseUserReportsRequest, AdminAbuseReportNotificationRecipientCreateResponse,
AdminAbuseUserReportsResponse, AdminAbuseReportNotificationRecipientDeleteRequest,
AdminAbuseReportNotificationRecipientListRequest, AdminAbuseReportNotificationRecipientListRequest,
AdminAbuseReportNotificationRecipientListResponse, AdminAbuseReportNotificationRecipientListResponse,
AdminAbuseReportNotificationRecipientShowRequest, AdminAbuseReportNotificationRecipientShowRequest,
AdminAbuseReportNotificationRecipientShowResponse, AdminAbuseReportNotificationRecipientShowResponse,
AdminAbuseReportNotificationRecipientCreateRequest,
AdminAbuseReportNotificationRecipientCreateResponse,
AdminAbuseReportNotificationRecipientUpdateRequest, AdminAbuseReportNotificationRecipientUpdateRequest,
AdminAbuseReportNotificationRecipientUpdateResponse, AdminAbuseReportNotificationRecipientUpdateResponse,
AdminAbuseReportNotificationRecipientDeleteRequest, AdminAbuseUserReportsRequest,
AdminAbuseUserReportsResponse,
AdminAccountsCreateRequest, AdminAccountsCreateRequest,
AdminAccountsCreateResponse, AdminAccountsCreateResponse,
AdminAccountsDeleteRequest, AdminAccountsDeleteRequest,
@ -38,25 +37,24 @@ import type {
AdminAvatarDecorationsUpdateRequest, AdminAvatarDecorationsUpdateRequest,
AdminCaptchaCurrentResponse, AdminCaptchaCurrentResponse,
AdminCaptchaSaveRequest, AdminCaptchaSaveRequest,
AdminDeleteAccountRequest,
AdminDeleteAllFilesOfAUserRequest, AdminDeleteAllFilesOfAUserRequest,
AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
AdminDriveFilesRequest, AdminDriveFilesRequest,
AdminDriveFilesResponse, AdminDriveFilesResponse,
AdminDriveShowFileRequest, AdminDriveShowFileRequest,
AdminDriveShowFileResponse, AdminDriveShowFileResponse,
AdminEmojiAddAliasesBulkRequest,
AdminEmojiAddRequest, AdminEmojiAddRequest,
AdminEmojiAddResponse, AdminEmojiAddResponse,
AdminEmojiAddAliasesBulkRequest,
AdminEmojiCopyRequest, AdminEmojiCopyRequest,
AdminEmojiCopyResponse, AdminEmojiCopyResponse,
AdminEmojiDeleteBulkRequest,
AdminEmojiDeleteRequest, AdminEmojiDeleteRequest,
AdminEmojiDeleteBulkRequest,
AdminEmojiImportZipRequest, AdminEmojiImportZipRequest,
AdminEmojiListRemoteRequest,
AdminEmojiListRemoteResponse,
AdminEmojiListRequest, AdminEmojiListRequest,
AdminEmojiListResponse, AdminEmojiListResponse,
AdminEmojiListRemoteRequest,
AdminEmojiListRemoteResponse,
AdminEmojiRemoveAliasesBulkRequest, AdminEmojiRemoveAliasesBulkRequest,
AdminEmojiSetAliasesBulkRequest, AdminEmojiSetAliasesBulkRequest,
AdminEmojiSetCategoryBulkRequest, AdminEmojiSetCategoryBulkRequest,
@ -66,6 +64,7 @@ import type {
AdminFederationRefreshRemoteInstanceMetadataRequest, AdminFederationRefreshRemoteInstanceMetadataRequest,
AdminFederationRemoveAllFollowingRequest, AdminFederationRemoveAllFollowingRequest,
AdminFederationUpdateInstanceRequest, AdminFederationUpdateInstanceRequest,
AdminForwardAbuseUserReportRequest,
AdminGetIndexStatsResponse, AdminGetIndexStatsResponse,
AdminGetTableStatsResponse, AdminGetTableStatsResponse,
AdminGetUserIpsRequest, AdminGetUserIpsRequest,
@ -74,6 +73,7 @@ import type {
AdminInviteCreateResponse, AdminInviteCreateResponse,
AdminInviteListRequest, AdminInviteListRequest,
AdminInviteListResponse, AdminInviteListResponse,
AdminMetaResponse,
AdminPromoCreateRequest, AdminPromoCreateRequest,
AdminQueueDeliverDelayedResponse, AdminQueueDeliverDelayedResponse,
AdminQueueInboxDelayedResponse, AdminQueueInboxDelayedResponse,
@ -86,8 +86,18 @@ import type {
AdminResetPasswordRequest, AdminResetPasswordRequest,
AdminResetPasswordResponse, AdminResetPasswordResponse,
AdminResolveAbuseUserReportRequest, AdminResolveAbuseUserReportRequest,
AdminForwardAbuseUserReportRequest, AdminRolesAssignRequest,
AdminUpdateAbuseUserReportRequest, AdminRolesCreateRequest,
AdminRolesCreateResponse,
AdminRolesDeleteRequest,
AdminRolesListResponse,
AdminRolesShowRequest,
AdminRolesShowResponse,
AdminRolesUnassignRequest,
AdminRolesUpdateRequest,
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSendEmailRequest, AdminSendEmailRequest,
AdminServerInfoResponse, AdminServerInfoResponse,
AdminShowModerationLogsRequest, AdminShowModerationLogsRequest,
@ -97,22 +107,6 @@ import type {
AdminShowUsersRequest, AdminShowUsersRequest,
AdminShowUsersResponse, AdminShowUsersResponse,
AdminSuspendUserRequest, AdminSuspendUserRequest,
AdminUnsuspendUserRequest,
AdminUpdateMetaRequest,
AdminDeleteAccountRequest,
AdminUpdateUserNoteRequest,
AdminRolesCreateRequest,
AdminRolesCreateResponse,
AdminRolesDeleteRequest,
AdminRolesListResponse,
AdminRolesShowRequest,
AdminRolesShowResponse,
AdminRolesUpdateRequest,
AdminRolesAssignRequest,
AdminRolesUnassignRequest,
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSystemWebhookCreateRequest, AdminSystemWebhookCreateRequest,
AdminSystemWebhookCreateResponse, AdminSystemWebhookCreateResponse,
AdminSystemWebhookDeleteRequest, AdminSystemWebhookDeleteRequest,
@ -120,9 +114,15 @@ import type {
AdminSystemWebhookListResponse, AdminSystemWebhookListResponse,
AdminSystemWebhookShowRequest, AdminSystemWebhookShowRequest,
AdminSystemWebhookShowResponse, AdminSystemWebhookShowResponse,
AdminSystemWebhookTestRequest,
AdminSystemWebhookUpdateRequest, AdminSystemWebhookUpdateRequest,
AdminSystemWebhookUpdateResponse, AdminSystemWebhookUpdateResponse,
AdminSystemWebhookTestRequest, AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
AdminUnsuspendUserRequest,
AdminUpdateAbuseUserReportRequest,
AdminUpdateMetaRequest,
AdminUpdateUserNoteRequest,
AnnouncementsRequest, AnnouncementsRequest,
AnnouncementsResponse, AnnouncementsResponse,
AnnouncementsShowRequest, AnnouncementsShowRequest,
@ -158,26 +158,29 @@ import type {
BlockingDeleteResponse, BlockingDeleteResponse,
BlockingListRequest, BlockingListRequest,
BlockingListResponse, BlockingListResponse,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
BubbleGameRegisterRequest,
ChannelsCreateRequest, ChannelsCreateRequest,
ChannelsCreateResponse, ChannelsCreateResponse,
ChannelsFavoriteRequest,
ChannelsFeaturedResponse, ChannelsFeaturedResponse,
ChannelsFollowRequest, ChannelsFollowRequest,
ChannelsFollowedRequest, ChannelsFollowedRequest,
ChannelsFollowedResponse, ChannelsFollowedResponse,
ChannelsMyFavoritesResponse,
ChannelsOwnedRequest, ChannelsOwnedRequest,
ChannelsOwnedResponse, ChannelsOwnedResponse,
ChannelsSearchRequest,
ChannelsSearchResponse,
ChannelsShowRequest, ChannelsShowRequest,
ChannelsShowResponse, ChannelsShowResponse,
ChannelsTimelineRequest, ChannelsTimelineRequest,
ChannelsTimelineResponse, ChannelsTimelineResponse,
ChannelsUnfavoriteRequest,
ChannelsUnfollowRequest, ChannelsUnfollowRequest,
ChannelsUpdateRequest, ChannelsUpdateRequest,
ChannelsUpdateResponse, ChannelsUpdateResponse,
ChannelsFavoriteRequest,
ChannelsUnfavoriteRequest,
ChannelsMyFavoritesResponse,
ChannelsSearchRequest,
ChannelsSearchResponse,
ChartsActiveUsersRequest, ChartsActiveUsersRequest,
ChartsActiveUsersResponse, ChartsActiveUsersResponse,
ChartsApRequestRequest, ChartsApRequestRequest,
@ -203,20 +206,20 @@ import type {
ChartsUsersRequest, ChartsUsersRequest,
ChartsUsersResponse, ChartsUsersResponse,
ClipsAddNoteRequest, ClipsAddNoteRequest,
ClipsRemoveNoteRequest,
ClipsCreateRequest, ClipsCreateRequest,
ClipsCreateResponse, ClipsCreateResponse,
ClipsDeleteRequest, ClipsDeleteRequest,
ClipsFavoriteRequest,
ClipsListResponse, ClipsListResponse,
ClipsMyFavoritesResponse,
ClipsNotesRequest, ClipsNotesRequest,
ClipsNotesResponse, ClipsNotesResponse,
ClipsRemoveNoteRequest,
ClipsShowRequest, ClipsShowRequest,
ClipsShowResponse, ClipsShowResponse,
ClipsUnfavoriteRequest,
ClipsUpdateRequest, ClipsUpdateRequest,
ClipsUpdateResponse, ClipsUpdateResponse,
ClipsFavoriteRequest,
ClipsUnfavoriteRequest,
ClipsMyFavoritesResponse,
DriveResponse, DriveResponse,
DriveFilesRequest, DriveFilesRequest,
DriveFilesResponse, DriveFilesResponse,
@ -227,10 +230,10 @@ import type {
DriveFilesCreateRequest, DriveFilesCreateRequest,
DriveFilesCreateResponse, DriveFilesCreateResponse,
DriveFilesDeleteRequest, DriveFilesDeleteRequest,
DriveFilesFindByHashRequest,
DriveFilesFindByHashResponse,
DriveFilesFindRequest, DriveFilesFindRequest,
DriveFilesFindResponse, DriveFilesFindResponse,
DriveFilesFindByHashRequest,
DriveFilesFindByHashResponse,
DriveFilesShowRequest, DriveFilesShowRequest,
DriveFilesShowResponse, DriveFilesShowResponse,
DriveFilesUpdateRequest, DriveFilesUpdateRequest,
@ -251,6 +254,9 @@ import type {
DriveStreamResponse, DriveStreamResponse,
EmailAddressAvailableRequest, EmailAddressAvailableRequest,
EmailAddressAvailableResponse, EmailAddressAvailableResponse,
EmojiRequest,
EmojiResponse,
EmojisResponse,
EndpointRequest, EndpointRequest,
EndpointResponse, EndpointResponse,
EndpointsResponse, EndpointsResponse,
@ -262,18 +268,33 @@ import type {
FederationInstancesResponse, FederationInstancesResponse,
FederationShowInstanceRequest, FederationShowInstanceRequest,
FederationShowInstanceResponse, FederationShowInstanceResponse,
FederationStatsRequest,
FederationStatsResponse,
FederationUpdateRemoteUserRequest, FederationUpdateRemoteUserRequest,
FederationUsersRequest, FederationUsersRequest,
FederationUsersResponse, FederationUsersResponse,
FederationStatsRequest, FetchExternalResourcesRequest,
FederationStatsResponse, FetchExternalResourcesResponse,
FetchRssRequest,
FetchRssResponse,
FlashCreateRequest,
FlashCreateResponse,
FlashDeleteRequest,
FlashFeaturedRequest,
FlashFeaturedResponse,
FlashLikeRequest,
FlashMyRequest,
FlashMyResponse,
FlashMyLikesRequest,
FlashMyLikesResponse,
FlashShowRequest,
FlashShowResponse,
FlashUnlikeRequest,
FlashUpdateRequest,
FollowingCreateRequest, FollowingCreateRequest,
FollowingCreateResponse, FollowingCreateResponse,
FollowingDeleteRequest, FollowingDeleteRequest,
FollowingDeleteResponse, FollowingDeleteResponse,
FollowingUpdateRequest,
FollowingUpdateResponse,
FollowingUpdateAllRequest,
FollowingInvalidateRequest, FollowingInvalidateRequest,
FollowingInvalidateResponse, FollowingInvalidateResponse,
FollowingRequestsAcceptRequest, FollowingRequestsAcceptRequest,
@ -281,9 +302,12 @@ import type {
FollowingRequestsCancelResponse, FollowingRequestsCancelResponse,
FollowingRequestsListRequest, FollowingRequestsListRequest,
FollowingRequestsListResponse, FollowingRequestsListResponse,
FollowingRequestsRejectRequest,
FollowingRequestsSentRequest, FollowingRequestsSentRequest,
FollowingRequestsSentResponse, FollowingRequestsSentResponse,
FollowingRequestsRejectRequest, FollowingUpdateRequest,
FollowingUpdateResponse,
FollowingUpdateAllRequest,
GalleryFeaturedRequest, GalleryFeaturedRequest,
GalleryFeaturedResponse, GalleryFeaturedResponse,
GalleryPopularResponse, GalleryPopularResponse,
@ -298,8 +322,8 @@ import type {
GalleryPostsUnlikeRequest, GalleryPostsUnlikeRequest,
GalleryPostsUpdateRequest, GalleryPostsUpdateRequest,
GalleryPostsUpdateResponse, GalleryPostsUpdateResponse,
GetOnlineUsersCountResponse,
GetAvatarDecorationsResponse, GetAvatarDecorationsResponse,
GetOnlineUsersCountResponse,
HashtagsListRequest, HashtagsListRequest,
HashtagsListResponse, HashtagsListResponse,
HashtagsSearchRequest, HashtagsSearchRequest,
@ -315,19 +339,19 @@ import type {
I2faKeyDoneRequest, I2faKeyDoneRequest,
I2faKeyDoneResponse, I2faKeyDoneResponse,
I2faPasswordLessRequest, I2faPasswordLessRequest,
I2faRegisterKeyRequest,
I2faRegisterKeyResponse,
I2faRegisterRequest, I2faRegisterRequest,
I2faRegisterResponse, I2faRegisterResponse,
I2faUpdateKeyRequest, I2faRegisterKeyRequest,
I2faRegisterKeyResponse,
I2faRemoveKeyRequest, I2faRemoveKeyRequest,
I2faUnregisterRequest, I2faUnregisterRequest,
I2faUpdateKeyRequest,
IAppsRequest, IAppsRequest,
IAppsResponse, IAppsResponse,
IAuthorizedAppsRequest, IAuthorizedAppsRequest,
IAuthorizedAppsResponse, IAuthorizedAppsResponse,
IClaimAchievementRequest,
IChangePasswordRequest, IChangePasswordRequest,
IClaimAchievementRequest,
IDeleteAccountRequest, IDeleteAccountRequest,
IExportFollowingRequest, IExportFollowingRequest,
IFavoritesRequest, IFavoritesRequest,
@ -336,11 +360,13 @@ import type {
IGalleryLikesResponse, IGalleryLikesResponse,
IGalleryPostsRequest, IGalleryPostsRequest,
IGalleryPostsResponse, IGalleryPostsResponse,
IImportAntennasRequest,
IImportBlockingRequest, IImportBlockingRequest,
IImportFollowingRequest, IImportFollowingRequest,
IImportMutingRequest, IImportMutingRequest,
IImportUserListsRequest, IImportUserListsRequest,
IImportAntennasRequest, IMoveRequest,
IMoveResponse,
INotificationsRequest, INotificationsRequest,
INotificationsResponse, INotificationsResponse,
INotificationsGroupedRequest, INotificationsGroupedRequest,
@ -353,16 +379,16 @@ import type {
IPinResponse, IPinResponse,
IReadAnnouncementRequest, IReadAnnouncementRequest,
IRegenerateTokenRequest, IRegenerateTokenRequest,
IRegistryGetRequest,
IRegistryGetResponse,
IRegistryGetAllRequest, IRegistryGetAllRequest,
IRegistryGetAllResponse, IRegistryGetAllResponse,
IRegistryGetDetailRequest, IRegistryGetDetailRequest,
IRegistryGetDetailResponse, IRegistryGetDetailResponse,
IRegistryGetRequest,
IRegistryGetResponse,
IRegistryKeysWithTypeRequest,
IRegistryKeysWithTypeResponse,
IRegistryKeysRequest, IRegistryKeysRequest,
IRegistryKeysResponse, IRegistryKeysResponse,
IRegistryKeysWithTypeRequest,
IRegistryKeysWithTypeResponse,
IRegistryRemoveRequest, IRegistryRemoveRequest,
IRegistryScopesWithDomainResponse, IRegistryScopesWithDomainResponse,
IRegistrySetRequest, IRegistrySetRequest,
@ -371,40 +397,31 @@ import type {
ISigninHistoryResponse, ISigninHistoryResponse,
IUnpinRequest, IUnpinRequest,
IUnpinResponse, IUnpinResponse,
IUpdateEmailRequest,
IUpdateEmailResponse,
IUpdateRequest, IUpdateRequest,
IUpdateResponse, IUpdateResponse,
IMoveRequest, IUpdateEmailRequest,
IMoveResponse, IUpdateEmailResponse,
IWebhooksCreateRequest, IWebhooksCreateRequest,
IWebhooksCreateResponse, IWebhooksCreateResponse,
IWebhooksDeleteRequest,
IWebhooksListResponse, IWebhooksListResponse,
IWebhooksShowRequest, IWebhooksShowRequest,
IWebhooksShowResponse, IWebhooksShowResponse,
IWebhooksUpdateRequest,
IWebhooksDeleteRequest,
IWebhooksTestRequest, IWebhooksTestRequest,
IWebhooksUpdateRequest,
InviteCreateResponse, InviteCreateResponse,
InviteDeleteRequest, InviteDeleteRequest,
InviteLimitResponse,
InviteListRequest, InviteListRequest,
InviteListResponse, InviteListResponse,
InviteLimitResponse,
MetaRequest, MetaRequest,
MetaResponse, MetaResponse,
EmojisResponse,
EmojiRequest,
EmojiResponse,
MiauthGenTokenRequest, MiauthGenTokenRequest,
MiauthGenTokenResponse, MiauthGenTokenResponse,
MuteCreateRequest, MuteCreateRequest,
MuteDeleteRequest, MuteDeleteRequest,
MuteListRequest, MuteListRequest,
MuteListResponse, MuteListResponse,
RenoteMuteCreateRequest,
RenoteMuteDeleteRequest,
RenoteMuteListRequest,
RenoteMuteListResponse,
MyAppsRequest, MyAppsRequest,
MyAppsResponse, MyAppsResponse,
NotesRequest, NotesRequest,
@ -441,10 +458,10 @@ import type {
NotesRenotesResponse, NotesRenotesResponse,
NotesRepliesRequest, NotesRepliesRequest,
NotesRepliesResponse, NotesRepliesResponse,
NotesSearchByTagRequest,
NotesSearchByTagResponse,
NotesSearchRequest, NotesSearchRequest,
NotesSearchResponse, NotesSearchResponse,
NotesSearchByTagRequest,
NotesSearchByTagResponse,
NotesShowRequest, NotesShowRequest,
NotesShowResponse, NotesShowResponse,
NotesStateRequest, NotesStateRequest,
@ -469,49 +486,57 @@ import type {
PagesShowResponse, PagesShowResponse,
PagesUnlikeRequest, PagesUnlikeRequest,
PagesUpdateRequest, PagesUpdateRequest,
FlashCreateRequest,
FlashCreateResponse,
FlashDeleteRequest,
FlashFeaturedRequest,
FlashFeaturedResponse,
FlashLikeRequest,
FlashShowRequest,
FlashShowResponse,
FlashUnlikeRequest,
FlashUpdateRequest,
FlashMyRequest,
FlashMyResponse,
FlashMyLikesRequest,
FlashMyLikesResponse,
PingResponse, PingResponse,
PinnedUsersResponse, PinnedUsersResponse,
PromoReadRequest, PromoReadRequest,
RenoteMuteCreateRequest,
RenoteMuteDeleteRequest,
RenoteMuteListRequest,
RenoteMuteListResponse,
RequestResetPasswordRequest,
ResetPasswordRequest,
RetentionResponse,
ReversiCancelMatchRequest,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiInvitationsResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
ReversiVerifyRequest,
ReversiVerifyResponse,
RolesListResponse, RolesListResponse,
RolesNotesRequest,
RolesNotesResponse,
RolesShowRequest, RolesShowRequest,
RolesShowResponse, RolesShowResponse,
RolesUsersRequest, RolesUsersRequest,
RolesUsersResponse, RolesUsersResponse,
RolesNotesRequest,
RolesNotesResponse,
RequestResetPasswordRequest,
ResetPasswordRequest,
ServerInfoResponse, ServerInfoResponse,
StatsResponse, StatsResponse,
SwShowRegistrationRequest,
SwShowRegistrationResponse,
SwUpdateRegistrationRequest,
SwUpdateRegistrationResponse,
SwRegisterRequest, SwRegisterRequest,
SwRegisterResponse, SwRegisterResponse,
SwShowRegistrationRequest,
SwShowRegistrationResponse,
SwUnregisterRequest, SwUnregisterRequest,
SwUpdateRegistrationRequest,
SwUpdateRegistrationResponse,
TestRequest, TestRequest,
TestResponse, TestResponse,
UsernameAvailableRequest, UsernameAvailableRequest,
UsernameAvailableResponse, UsernameAvailableResponse,
UsersRequest, UsersRequest,
UsersResponse, UsersResponse,
UsersAchievementsRequest,
UsersAchievementsResponse,
UsersClipsRequest, UsersClipsRequest,
UsersClipsResponse, UsersClipsResponse,
UsersFeaturedNotesRequest,
UsersFeaturedNotesResponse,
UsersFlashsRequest,
UsersFlashsResponse,
UsersFollowersRequest, UsersFollowersRequest,
UsersFollowersResponse, UsersFollowersResponse,
UsersFollowingRequest, UsersFollowingRequest,
@ -520,32 +545,28 @@ import type {
UsersGalleryPostsResponse, UsersGalleryPostsResponse,
UsersGetFrequentlyRepliedUsersRequest, UsersGetFrequentlyRepliedUsersRequest,
UsersGetFrequentlyRepliedUsersResponse, UsersGetFrequentlyRepliedUsersResponse,
UsersFeaturedNotesRequest,
UsersFeaturedNotesResponse,
UsersListsCreateRequest, UsersListsCreateRequest,
UsersListsCreateResponse, UsersListsCreateResponse,
UsersListsCreateFromPublicRequest,
UsersListsCreateFromPublicResponse,
UsersListsDeleteRequest, UsersListsDeleteRequest,
UsersListsFavoriteRequest,
UsersListsGetMembershipsRequest,
UsersListsGetMembershipsResponse,
UsersListsListRequest, UsersListsListRequest,
UsersListsListResponse, UsersListsListResponse,
UsersListsPullRequest, UsersListsPullRequest,
UsersListsPushRequest, UsersListsPushRequest,
UsersListsShowRequest, UsersListsShowRequest,
UsersListsShowResponse, UsersListsShowResponse,
UsersListsFavoriteRequest,
UsersListsUnfavoriteRequest, UsersListsUnfavoriteRequest,
UsersListsUpdateRequest, UsersListsUpdateRequest,
UsersListsUpdateResponse, UsersListsUpdateResponse,
UsersListsCreateFromPublicRequest,
UsersListsCreateFromPublicResponse,
UsersListsUpdateMembershipRequest, UsersListsUpdateMembershipRequest,
UsersListsGetMembershipsRequest,
UsersListsGetMembershipsResponse,
UsersNotesRequest, UsersNotesRequest,
UsersNotesResponse, UsersNotesResponse,
UsersPagesRequest, UsersPagesRequest,
UsersPagesResponse, UsersPagesResponse,
UsersFlashsRequest,
UsersFlashsResponse,
UsersReactionsRequest, UsersReactionsRequest,
UsersReactionsResponse, UsersReactionsResponse,
UsersRecommendationRequest, UsersRecommendationRequest,
@ -553,44 +574,24 @@ import type {
UsersRelationRequest, UsersRelationRequest,
UsersRelationResponse, UsersRelationResponse,
UsersReportAbuseRequest, UsersReportAbuseRequest,
UsersSearchByUsernameAndHostRequest,
UsersSearchByUsernameAndHostResponse,
UsersSearchRequest, UsersSearchRequest,
UsersSearchResponse, UsersSearchResponse,
UsersSearchByUsernameAndHostRequest,
UsersSearchByUsernameAndHostResponse,
UsersShowRequest, UsersShowRequest,
UsersShowResponse, UsersShowResponse,
UsersAchievementsRequest,
UsersAchievementsResponse,
UsersUpdateMemoRequest, UsersUpdateMemoRequest,
FetchRssRequest, V2AdminEmojiListRequest,
FetchRssResponse, V2AdminEmojiListResponse,
FetchExternalResourcesRequest,
FetchExternalResourcesResponse,
RetentionResponse,
BubbleGameRegisterRequest,
BubbleGameRankingRequest,
BubbleGameRankingResponse,
ReversiCancelMatchRequest,
ReversiGamesRequest,
ReversiGamesResponse,
ReversiMatchRequest,
ReversiMatchResponse,
ReversiInvitationsResponse,
ReversiShowGameRequest,
ReversiShowGameResponse,
ReversiSurrenderRequest,
ReversiVerifyRequest,
ReversiVerifyResponse,
} from './entities.js'; } from './entities.js';
export type Endpoints = { export type Endpoints = {
'admin/meta': { req: EmptyRequest; res: AdminMetaResponse }; 'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse };
'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse }; 'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse };
'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse }; 'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse };
'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse }; 'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse };
'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse };
'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse }; 'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse };
'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse }; 'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse };
'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse }; 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse };
'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse }; 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse };
'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse }; 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse };
@ -608,21 +609,20 @@ export type Endpoints = {
'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse }; 'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse };
'admin/captcha/current': { req: EmptyRequest; res: AdminCaptchaCurrentResponse }; 'admin/captcha/current': { req: EmptyRequest; res: AdminCaptchaCurrentResponse };
'admin/captcha/save': { req: AdminCaptchaSaveRequest; res: EmptyResponse }; 'admin/captcha/save': { req: AdminCaptchaSaveRequest; res: EmptyResponse };
'admin/delete-account': { req: AdminDeleteAccountRequest; res: EmptyResponse };
'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse }; 'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse };
'admin/unset-user-avatar': { req: AdminUnsetUserAvatarRequest; res: EmptyResponse };
'admin/unset-user-banner': { req: AdminUnsetUserBannerRequest; res: EmptyResponse };
'admin/drive/clean-remote-files': { req: EmptyRequest; res: EmptyResponse }; 'admin/drive/clean-remote-files': { req: EmptyRequest; res: EmptyResponse };
'admin/drive/cleanup': { req: EmptyRequest; res: EmptyResponse }; 'admin/drive/cleanup': { req: EmptyRequest; res: EmptyResponse };
'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse }; 'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse };
'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse }; 'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse };
'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse };
'admin/emoji/add': { req: AdminEmojiAddRequest; res: AdminEmojiAddResponse }; 'admin/emoji/add': { req: AdminEmojiAddRequest; res: AdminEmojiAddResponse };
'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse };
'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse }; 'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse };
'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse };
'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse }; 'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse };
'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse };
'admin/emoji/import-zip': { req: AdminEmojiImportZipRequest; res: EmptyResponse }; 'admin/emoji/import-zip': { req: AdminEmojiImportZipRequest; res: EmptyResponse };
'admin/emoji/list-remote': { req: AdminEmojiListRemoteRequest; res: AdminEmojiListRemoteResponse };
'admin/emoji/list': { req: AdminEmojiListRequest; res: AdminEmojiListResponse }; 'admin/emoji/list': { req: AdminEmojiListRequest; res: AdminEmojiListResponse };
'admin/emoji/list-remote': { req: AdminEmojiListRemoteRequest; res: AdminEmojiListRemoteResponse };
'admin/emoji/remove-aliases-bulk': { req: AdminEmojiRemoveAliasesBulkRequest; res: EmptyResponse }; 'admin/emoji/remove-aliases-bulk': { req: AdminEmojiRemoveAliasesBulkRequest; res: EmptyResponse };
'admin/emoji/set-aliases-bulk': { req: AdminEmojiSetAliasesBulkRequest; res: EmptyResponse }; 'admin/emoji/set-aliases-bulk': { req: AdminEmojiSetAliasesBulkRequest; res: EmptyResponse };
'admin/emoji/set-category-bulk': { req: AdminEmojiSetCategoryBulkRequest; res: EmptyResponse }; 'admin/emoji/set-category-bulk': { req: AdminEmojiSetCategoryBulkRequest; res: EmptyResponse };
@ -632,11 +632,13 @@ export type Endpoints = {
'admin/federation/refresh-remote-instance-metadata': { req: AdminFederationRefreshRemoteInstanceMetadataRequest; res: EmptyResponse }; 'admin/federation/refresh-remote-instance-metadata': { req: AdminFederationRefreshRemoteInstanceMetadataRequest; res: EmptyResponse };
'admin/federation/remove-all-following': { req: AdminFederationRemoveAllFollowingRequest; res: EmptyResponse }; 'admin/federation/remove-all-following': { req: AdminFederationRemoveAllFollowingRequest; res: EmptyResponse };
'admin/federation/update-instance': { req: AdminFederationUpdateInstanceRequest; res: EmptyResponse }; 'admin/federation/update-instance': { req: AdminFederationUpdateInstanceRequest; res: EmptyResponse };
'admin/forward-abuse-user-report': { req: AdminForwardAbuseUserReportRequest; res: EmptyResponse };
'admin/get-index-stats': { req: EmptyRequest; res: AdminGetIndexStatsResponse }; 'admin/get-index-stats': { req: EmptyRequest; res: AdminGetIndexStatsResponse };
'admin/get-table-stats': { req: EmptyRequest; res: AdminGetTableStatsResponse }; 'admin/get-table-stats': { req: EmptyRequest; res: AdminGetTableStatsResponse };
'admin/get-user-ips': { req: AdminGetUserIpsRequest; res: AdminGetUserIpsResponse }; 'admin/get-user-ips': { req: AdminGetUserIpsRequest; res: AdminGetUserIpsResponse };
'admin/invite/create': { req: AdminInviteCreateRequest; res: AdminInviteCreateResponse }; 'admin/invite/create': { req: AdminInviteCreateRequest; res: AdminInviteCreateResponse };
'admin/invite/list': { req: AdminInviteListRequest; res: AdminInviteListResponse }; 'admin/invite/list': { req: AdminInviteListRequest; res: AdminInviteListResponse };
'admin/meta': { req: EmptyRequest; res: AdminMetaResponse };
'admin/promo/create': { req: AdminPromoCreateRequest; res: EmptyResponse }; 'admin/promo/create': { req: AdminPromoCreateRequest; res: EmptyResponse };
'admin/queue/clear': { req: EmptyRequest; res: EmptyResponse }; 'admin/queue/clear': { req: EmptyRequest; res: EmptyResponse };
'admin/queue/deliver-delayed': { req: EmptyRequest; res: AdminQueueDeliverDelayedResponse }; 'admin/queue/deliver-delayed': { req: EmptyRequest; res: AdminQueueDeliverDelayedResponse };
@ -648,33 +650,33 @@ export type Endpoints = {
'admin/relays/remove': { req: AdminRelaysRemoveRequest; res: EmptyResponse }; 'admin/relays/remove': { req: AdminRelaysRemoveRequest; res: EmptyResponse };
'admin/reset-password': { req: AdminResetPasswordRequest; res: AdminResetPasswordResponse }; 'admin/reset-password': { req: AdminResetPasswordRequest; res: AdminResetPasswordResponse };
'admin/resolve-abuse-user-report': { req: AdminResolveAbuseUserReportRequest; res: EmptyResponse }; 'admin/resolve-abuse-user-report': { req: AdminResolveAbuseUserReportRequest; res: EmptyResponse };
'admin/forward-abuse-user-report': { req: AdminForwardAbuseUserReportRequest; res: EmptyResponse }; 'admin/roles/assign': { req: AdminRolesAssignRequest; res: EmptyResponse };
'admin/update-abuse-user-report': { req: AdminUpdateAbuseUserReportRequest; res: EmptyResponse }; 'admin/roles/create': { req: AdminRolesCreateRequest; res: AdminRolesCreateResponse };
'admin/roles/delete': { req: AdminRolesDeleteRequest; res: EmptyResponse };
'admin/roles/list': { req: EmptyRequest; res: AdminRolesListResponse };
'admin/roles/show': { req: AdminRolesShowRequest; res: AdminRolesShowResponse };
'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse };
'admin/roles/update': { req: AdminRolesUpdateRequest; res: EmptyResponse };
'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse };
'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse };
'admin/send-email': { req: AdminSendEmailRequest; res: EmptyResponse }; 'admin/send-email': { req: AdminSendEmailRequest; res: EmptyResponse };
'admin/server-info': { req: EmptyRequest; res: AdminServerInfoResponse }; 'admin/server-info': { req: EmptyRequest; res: AdminServerInfoResponse };
'admin/show-moderation-logs': { req: AdminShowModerationLogsRequest; res: AdminShowModerationLogsResponse }; 'admin/show-moderation-logs': { req: AdminShowModerationLogsRequest; res: AdminShowModerationLogsResponse };
'admin/show-user': { req: AdminShowUserRequest; res: AdminShowUserResponse }; 'admin/show-user': { req: AdminShowUserRequest; res: AdminShowUserResponse };
'admin/show-users': { req: AdminShowUsersRequest; res: AdminShowUsersResponse }; 'admin/show-users': { req: AdminShowUsersRequest; res: AdminShowUsersResponse };
'admin/suspend-user': { req: AdminSuspendUserRequest; res: EmptyResponse }; 'admin/suspend-user': { req: AdminSuspendUserRequest; res: EmptyResponse };
'admin/unsuspend-user': { req: AdminUnsuspendUserRequest; res: EmptyResponse };
'admin/update-meta': { req: AdminUpdateMetaRequest; res: EmptyResponse };
'admin/delete-account': { req: AdminDeleteAccountRequest; res: EmptyResponse };
'admin/update-user-note': { req: AdminUpdateUserNoteRequest; res: EmptyResponse };
'admin/roles/create': { req: AdminRolesCreateRequest; res: AdminRolesCreateResponse };
'admin/roles/delete': { req: AdminRolesDeleteRequest; res: EmptyResponse };
'admin/roles/list': { req: EmptyRequest; res: AdminRolesListResponse };
'admin/roles/show': { req: AdminRolesShowRequest; res: AdminRolesShowResponse };
'admin/roles/update': { req: AdminRolesUpdateRequest; res: EmptyResponse };
'admin/roles/assign': { req: AdminRolesAssignRequest; res: EmptyResponse };
'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse };
'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse };
'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse };
'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse }; 'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse };
'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse }; 'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse };
'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse }; 'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse };
'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse }; 'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse };
'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse };
'admin/system-webhook/test': { req: AdminSystemWebhookTestRequest; res: EmptyResponse }; 'admin/system-webhook/test': { req: AdminSystemWebhookTestRequest; res: EmptyResponse };
'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse };
'admin/unset-user-avatar': { req: AdminUnsetUserAvatarRequest; res: EmptyResponse };
'admin/unset-user-banner': { req: AdminUnsetUserBannerRequest; res: EmptyResponse };
'admin/unsuspend-user': { req: AdminUnsuspendUserRequest; res: EmptyResponse };
'admin/update-abuse-user-report': { req: AdminUpdateAbuseUserReportRequest; res: EmptyResponse };
'admin/update-meta': { req: AdminUpdateMetaRequest; res: EmptyResponse };
'admin/update-user-note': { req: AdminUpdateUserNoteRequest; res: EmptyResponse };
'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse }; 'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse };
'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse }; 'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse };
'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse }; 'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse };
@ -694,19 +696,21 @@ export type Endpoints = {
'blocking/create': { req: BlockingCreateRequest; res: BlockingCreateResponse }; 'blocking/create': { req: BlockingCreateRequest; res: BlockingCreateResponse };
'blocking/delete': { req: BlockingDeleteRequest; res: BlockingDeleteResponse }; 'blocking/delete': { req: BlockingDeleteRequest; res: BlockingDeleteResponse };
'blocking/list': { req: BlockingListRequest; res: BlockingListResponse }; 'blocking/list': { req: BlockingListRequest; res: BlockingListResponse };
'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse };
'bubble-game/register': { req: BubbleGameRegisterRequest; res: EmptyResponse };
'channels/create': { req: ChannelsCreateRequest; res: ChannelsCreateResponse }; 'channels/create': { req: ChannelsCreateRequest; res: ChannelsCreateResponse };
'channels/favorite': { req: ChannelsFavoriteRequest; res: EmptyResponse };
'channels/featured': { req: EmptyRequest; res: ChannelsFeaturedResponse }; 'channels/featured': { req: EmptyRequest; res: ChannelsFeaturedResponse };
'channels/follow': { req: ChannelsFollowRequest; res: EmptyResponse }; 'channels/follow': { req: ChannelsFollowRequest; res: EmptyResponse };
'channels/followed': { req: ChannelsFollowedRequest; res: ChannelsFollowedResponse }; 'channels/followed': { req: ChannelsFollowedRequest; res: ChannelsFollowedResponse };
'channels/my-favorites': { req: EmptyRequest; res: ChannelsMyFavoritesResponse };
'channels/owned': { req: ChannelsOwnedRequest; res: ChannelsOwnedResponse }; 'channels/owned': { req: ChannelsOwnedRequest; res: ChannelsOwnedResponse };
'channels/search': { req: ChannelsSearchRequest; res: ChannelsSearchResponse };
'channels/show': { req: ChannelsShowRequest; res: ChannelsShowResponse }; 'channels/show': { req: ChannelsShowRequest; res: ChannelsShowResponse };
'channels/timeline': { req: ChannelsTimelineRequest; res: ChannelsTimelineResponse }; 'channels/timeline': { req: ChannelsTimelineRequest; res: ChannelsTimelineResponse };
'channels/unfavorite': { req: ChannelsUnfavoriteRequest; res: EmptyResponse };
'channels/unfollow': { req: ChannelsUnfollowRequest; res: EmptyResponse }; 'channels/unfollow': { req: ChannelsUnfollowRequest; res: EmptyResponse };
'channels/update': { req: ChannelsUpdateRequest; res: ChannelsUpdateResponse }; 'channels/update': { req: ChannelsUpdateRequest; res: ChannelsUpdateResponse };
'channels/favorite': { req: ChannelsFavoriteRequest; res: EmptyResponse };
'channels/unfavorite': { req: ChannelsUnfavoriteRequest; res: EmptyResponse };
'channels/my-favorites': { req: EmptyRequest; res: ChannelsMyFavoritesResponse };
'channels/search': { req: ChannelsSearchRequest; res: ChannelsSearchResponse };
'charts/active-users': { req: ChartsActiveUsersRequest; res: ChartsActiveUsersResponse }; 'charts/active-users': { req: ChartsActiveUsersRequest; res: ChartsActiveUsersResponse };
'charts/ap-request': { req: ChartsApRequestRequest; res: ChartsApRequestResponse }; 'charts/ap-request': { req: ChartsApRequestRequest; res: ChartsApRequestResponse };
'charts/drive': { req: ChartsDriveRequest; res: ChartsDriveResponse }; 'charts/drive': { req: ChartsDriveRequest; res: ChartsDriveResponse };
@ -720,24 +724,24 @@ export type Endpoints = {
'charts/user/reactions': { req: ChartsUserReactionsRequest; res: ChartsUserReactionsResponse }; 'charts/user/reactions': { req: ChartsUserReactionsRequest; res: ChartsUserReactionsResponse };
'charts/users': { req: ChartsUsersRequest; res: ChartsUsersResponse }; 'charts/users': { req: ChartsUsersRequest; res: ChartsUsersResponse };
'clips/add-note': { req: ClipsAddNoteRequest; res: EmptyResponse }; 'clips/add-note': { req: ClipsAddNoteRequest; res: EmptyResponse };
'clips/remove-note': { req: ClipsRemoveNoteRequest; res: EmptyResponse };
'clips/create': { req: ClipsCreateRequest; res: ClipsCreateResponse }; 'clips/create': { req: ClipsCreateRequest; res: ClipsCreateResponse };
'clips/delete': { req: ClipsDeleteRequest; res: EmptyResponse }; 'clips/delete': { req: ClipsDeleteRequest; res: EmptyResponse };
'clips/list': { req: EmptyRequest; res: ClipsListResponse };
'clips/notes': { req: ClipsNotesRequest; res: ClipsNotesResponse };
'clips/show': { req: ClipsShowRequest; res: ClipsShowResponse };
'clips/update': { req: ClipsUpdateRequest; res: ClipsUpdateResponse };
'clips/favorite': { req: ClipsFavoriteRequest; res: EmptyResponse }; 'clips/favorite': { req: ClipsFavoriteRequest; res: EmptyResponse };
'clips/unfavorite': { req: ClipsUnfavoriteRequest; res: EmptyResponse }; 'clips/list': { req: EmptyRequest; res: ClipsListResponse };
'clips/my-favorites': { req: EmptyRequest; res: ClipsMyFavoritesResponse }; 'clips/my-favorites': { req: EmptyRequest; res: ClipsMyFavoritesResponse };
'clips/notes': { req: ClipsNotesRequest; res: ClipsNotesResponse };
'clips/remove-note': { req: ClipsRemoveNoteRequest; res: EmptyResponse };
'clips/show': { req: ClipsShowRequest; res: ClipsShowResponse };
'clips/unfavorite': { req: ClipsUnfavoriteRequest; res: EmptyResponse };
'clips/update': { req: ClipsUpdateRequest; res: ClipsUpdateResponse };
'drive': { req: EmptyRequest; res: DriveResponse }; 'drive': { req: EmptyRequest; res: DriveResponse };
'drive/files': { req: DriveFilesRequest; res: DriveFilesResponse }; 'drive/files': { req: DriveFilesRequest; res: DriveFilesResponse };
'drive/files/attached-notes': { req: DriveFilesAttachedNotesRequest; res: DriveFilesAttachedNotesResponse }; 'drive/files/attached-notes': { req: DriveFilesAttachedNotesRequest; res: DriveFilesAttachedNotesResponse };
'drive/files/check-existence': { req: DriveFilesCheckExistenceRequest; res: DriveFilesCheckExistenceResponse }; 'drive/files/check-existence': { req: DriveFilesCheckExistenceRequest; res: DriveFilesCheckExistenceResponse };
'drive/files/create': { req: DriveFilesCreateRequest; res: DriveFilesCreateResponse }; 'drive/files/create': { req: DriveFilesCreateRequest; res: DriveFilesCreateResponse };
'drive/files/delete': { req: DriveFilesDeleteRequest; res: EmptyResponse }; 'drive/files/delete': { req: DriveFilesDeleteRequest; res: EmptyResponse };
'drive/files/find-by-hash': { req: DriveFilesFindByHashRequest; res: DriveFilesFindByHashResponse };
'drive/files/find': { req: DriveFilesFindRequest; res: DriveFilesFindResponse }; 'drive/files/find': { req: DriveFilesFindRequest; res: DriveFilesFindResponse };
'drive/files/find-by-hash': { req: DriveFilesFindByHashRequest; res: DriveFilesFindByHashResponse };
'drive/files/show': { req: DriveFilesShowRequest; res: DriveFilesShowResponse }; 'drive/files/show': { req: DriveFilesShowRequest; res: DriveFilesShowResponse };
'drive/files/update': { req: DriveFilesUpdateRequest; res: DriveFilesUpdateResponse }; 'drive/files/update': { req: DriveFilesUpdateRequest; res: DriveFilesUpdateResponse };
'drive/files/upload-from-url': { req: DriveFilesUploadFromUrlRequest; res: EmptyResponse }; 'drive/files/upload-from-url': { req: DriveFilesUploadFromUrlRequest; res: EmptyResponse };
@ -749,6 +753,8 @@ export type Endpoints = {
'drive/folders/update': { req: DriveFoldersUpdateRequest; res: DriveFoldersUpdateResponse }; 'drive/folders/update': { req: DriveFoldersUpdateRequest; res: DriveFoldersUpdateResponse };
'drive/stream': { req: DriveStreamRequest; res: DriveStreamResponse }; 'drive/stream': { req: DriveStreamRequest; res: DriveStreamResponse };
'email-address/available': { req: EmailAddressAvailableRequest; res: EmailAddressAvailableResponse }; 'email-address/available': { req: EmailAddressAvailableRequest; res: EmailAddressAvailableResponse };
'emoji': { req: EmojiRequest; res: EmojiResponse };
'emojis': { req: EmptyRequest; res: EmojisResponse };
'endpoint': { req: EndpointRequest; res: EndpointResponse }; 'endpoint': { req: EndpointRequest; res: EndpointResponse };
'endpoints': { req: EmptyRequest; res: EndpointsResponse }; 'endpoints': { req: EmptyRequest; res: EndpointsResponse };
'export-custom-emojis': { req: EmptyRequest; res: EmptyResponse }; 'export-custom-emojis': { req: EmptyRequest; res: EmptyResponse };
@ -756,19 +762,30 @@ export type Endpoints = {
'federation/following': { req: FederationFollowingRequest; res: FederationFollowingResponse }; 'federation/following': { req: FederationFollowingRequest; res: FederationFollowingResponse };
'federation/instances': { req: FederationInstancesRequest; res: FederationInstancesResponse }; 'federation/instances': { req: FederationInstancesRequest; res: FederationInstancesResponse };
'federation/show-instance': { req: FederationShowInstanceRequest; res: FederationShowInstanceResponse }; 'federation/show-instance': { req: FederationShowInstanceRequest; res: FederationShowInstanceResponse };
'federation/stats': { req: FederationStatsRequest; res: FederationStatsResponse };
'federation/update-remote-user': { req: FederationUpdateRemoteUserRequest; res: EmptyResponse }; 'federation/update-remote-user': { req: FederationUpdateRemoteUserRequest; res: EmptyResponse };
'federation/users': { req: FederationUsersRequest; res: FederationUsersResponse }; 'federation/users': { req: FederationUsersRequest; res: FederationUsersResponse };
'federation/stats': { req: FederationStatsRequest; res: FederationStatsResponse }; 'fetch-external-resources': { req: FetchExternalResourcesRequest; res: FetchExternalResourcesResponse };
'fetch-rss': { req: FetchRssRequest; res: FetchRssResponse };
'flash/create': { req: FlashCreateRequest; res: FlashCreateResponse };
'flash/delete': { req: FlashDeleteRequest; res: EmptyResponse };
'flash/featured': { req: FlashFeaturedRequest; res: FlashFeaturedResponse };
'flash/like': { req: FlashLikeRequest; res: EmptyResponse };
'flash/my': { req: FlashMyRequest; res: FlashMyResponse };
'flash/my-likes': { req: FlashMyLikesRequest; res: FlashMyLikesResponse };
'flash/show': { req: FlashShowRequest; res: FlashShowResponse };
'flash/unlike': { req: FlashUnlikeRequest; res: EmptyResponse };
'flash/update': { req: FlashUpdateRequest; res: EmptyResponse };
'following/create': { req: FollowingCreateRequest; res: FollowingCreateResponse }; 'following/create': { req: FollowingCreateRequest; res: FollowingCreateResponse };
'following/delete': { req: FollowingDeleteRequest; res: FollowingDeleteResponse }; 'following/delete': { req: FollowingDeleteRequest; res: FollowingDeleteResponse };
'following/update': { req: FollowingUpdateRequest; res: FollowingUpdateResponse };
'following/update-all': { req: FollowingUpdateAllRequest; res: EmptyResponse };
'following/invalidate': { req: FollowingInvalidateRequest; res: FollowingInvalidateResponse }; 'following/invalidate': { req: FollowingInvalidateRequest; res: FollowingInvalidateResponse };
'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse }; 'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse };
'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse }; 'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse };
'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse }; 'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse };
'following/requests/sent': { req: FollowingRequestsSentRequest; res: FollowingRequestsSentResponse };
'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse }; 'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse };
'following/requests/sent': { req: FollowingRequestsSentRequest; res: FollowingRequestsSentResponse };
'following/update': { req: FollowingUpdateRequest; res: FollowingUpdateResponse };
'following/update-all': { req: FollowingUpdateAllRequest; res: EmptyResponse };
'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse }; 'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse };
'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse }; 'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse };
'gallery/posts': { req: GalleryPostsRequest; res: GalleryPostsResponse }; 'gallery/posts': { req: GalleryPostsRequest; res: GalleryPostsResponse };
@ -778,8 +795,8 @@ export type Endpoints = {
'gallery/posts/show': { req: GalleryPostsShowRequest; res: GalleryPostsShowResponse }; 'gallery/posts/show': { req: GalleryPostsShowRequest; res: GalleryPostsShowResponse };
'gallery/posts/unlike': { req: GalleryPostsUnlikeRequest; res: EmptyResponse }; 'gallery/posts/unlike': { req: GalleryPostsUnlikeRequest; res: EmptyResponse };
'gallery/posts/update': { req: GalleryPostsUpdateRequest; res: GalleryPostsUpdateResponse }; 'gallery/posts/update': { req: GalleryPostsUpdateRequest; res: GalleryPostsUpdateResponse };
'get-online-users-count': { req: EmptyRequest; res: GetOnlineUsersCountResponse };
'get-avatar-decorations': { req: EmptyRequest; res: GetAvatarDecorationsResponse }; 'get-avatar-decorations': { req: EmptyRequest; res: GetAvatarDecorationsResponse };
'get-online-users-count': { req: EmptyRequest; res: GetOnlineUsersCountResponse };
'hashtags/list': { req: HashtagsListRequest; res: HashtagsListResponse }; 'hashtags/list': { req: HashtagsListRequest; res: HashtagsListResponse };
'hashtags/search': { req: HashtagsSearchRequest; res: HashtagsSearchResponse }; 'hashtags/search': { req: HashtagsSearchRequest; res: HashtagsSearchResponse };
'hashtags/show': { req: HashtagsShowRequest; res: HashtagsShowResponse }; 'hashtags/show': { req: HashtagsShowRequest; res: HashtagsShowResponse };
@ -789,32 +806,33 @@ export type Endpoints = {
'i/2fa/done': { req: I2faDoneRequest; res: I2faDoneResponse }; 'i/2fa/done': { req: I2faDoneRequest; res: I2faDoneResponse };
'i/2fa/key-done': { req: I2faKeyDoneRequest; res: I2faKeyDoneResponse }; 'i/2fa/key-done': { req: I2faKeyDoneRequest; res: I2faKeyDoneResponse };
'i/2fa/password-less': { req: I2faPasswordLessRequest; res: EmptyResponse }; 'i/2fa/password-less': { req: I2faPasswordLessRequest; res: EmptyResponse };
'i/2fa/register-key': { req: I2faRegisterKeyRequest; res: I2faRegisterKeyResponse };
'i/2fa/register': { req: I2faRegisterRequest; res: I2faRegisterResponse }; 'i/2fa/register': { req: I2faRegisterRequest; res: I2faRegisterResponse };
'i/2fa/update-key': { req: I2faUpdateKeyRequest; res: EmptyResponse }; 'i/2fa/register-key': { req: I2faRegisterKeyRequest; res: I2faRegisterKeyResponse };
'i/2fa/remove-key': { req: I2faRemoveKeyRequest; res: EmptyResponse }; 'i/2fa/remove-key': { req: I2faRemoveKeyRequest; res: EmptyResponse };
'i/2fa/unregister': { req: I2faUnregisterRequest; res: EmptyResponse }; 'i/2fa/unregister': { req: I2faUnregisterRequest; res: EmptyResponse };
'i/2fa/update-key': { req: I2faUpdateKeyRequest; res: EmptyResponse };
'i/apps': { req: IAppsRequest; res: IAppsResponse }; 'i/apps': { req: IAppsRequest; res: IAppsResponse };
'i/authorized-apps': { req: IAuthorizedAppsRequest; res: IAuthorizedAppsResponse }; 'i/authorized-apps': { req: IAuthorizedAppsRequest; res: IAuthorizedAppsResponse };
'i/claim-achievement': { req: IClaimAchievementRequest; res: EmptyResponse };
'i/change-password': { req: IChangePasswordRequest; res: EmptyResponse }; 'i/change-password': { req: IChangePasswordRequest; res: EmptyResponse };
'i/claim-achievement': { req: IClaimAchievementRequest; res: EmptyResponse };
'i/delete-account': { req: IDeleteAccountRequest; res: EmptyResponse }; 'i/delete-account': { req: IDeleteAccountRequest; res: EmptyResponse };
'i/export-antennas': { req: EmptyRequest; res: EmptyResponse };
'i/export-blocking': { req: EmptyRequest; res: EmptyResponse }; 'i/export-blocking': { req: EmptyRequest; res: EmptyResponse };
'i/export-clips': { req: EmptyRequest; res: EmptyResponse };
'i/export-favorites': { req: EmptyRequest; res: EmptyResponse };
'i/export-following': { req: IExportFollowingRequest; res: EmptyResponse }; 'i/export-following': { req: IExportFollowingRequest; res: EmptyResponse };
'i/export-mute': { req: EmptyRequest; res: EmptyResponse }; 'i/export-mute': { req: EmptyRequest; res: EmptyResponse };
'i/export-notes': { req: EmptyRequest; res: EmptyResponse }; 'i/export-notes': { req: EmptyRequest; res: EmptyResponse };
'i/export-clips': { req: EmptyRequest; res: EmptyResponse };
'i/export-favorites': { req: EmptyRequest; res: EmptyResponse };
'i/export-user-lists': { req: EmptyRequest; res: EmptyResponse }; 'i/export-user-lists': { req: EmptyRequest; res: EmptyResponse };
'i/export-antennas': { req: EmptyRequest; res: EmptyResponse };
'i/favorites': { req: IFavoritesRequest; res: IFavoritesResponse }; 'i/favorites': { req: IFavoritesRequest; res: IFavoritesResponse };
'i/gallery/likes': { req: IGalleryLikesRequest; res: IGalleryLikesResponse }; 'i/gallery/likes': { req: IGalleryLikesRequest; res: IGalleryLikesResponse };
'i/gallery/posts': { req: IGalleryPostsRequest; res: IGalleryPostsResponse }; 'i/gallery/posts': { req: IGalleryPostsRequest; res: IGalleryPostsResponse };
'i/import-antennas': { req: IImportAntennasRequest; res: EmptyResponse };
'i/import-blocking': { req: IImportBlockingRequest; res: EmptyResponse }; 'i/import-blocking': { req: IImportBlockingRequest; res: EmptyResponse };
'i/import-following': { req: IImportFollowingRequest; res: EmptyResponse }; 'i/import-following': { req: IImportFollowingRequest; res: EmptyResponse };
'i/import-muting': { req: IImportMutingRequest; res: EmptyResponse }; 'i/import-muting': { req: IImportMutingRequest; res: EmptyResponse };
'i/import-user-lists': { req: IImportUserListsRequest; res: EmptyResponse }; 'i/import-user-lists': { req: IImportUserListsRequest; res: EmptyResponse };
'i/import-antennas': { req: IImportAntennasRequest; res: EmptyResponse }; 'i/move': { req: IMoveRequest; res: IMoveResponse };
'i/notifications': { req: INotificationsRequest; res: INotificationsResponse }; 'i/notifications': { req: INotificationsRequest; res: INotificationsResponse };
'i/notifications-grouped': { req: INotificationsGroupedRequest; res: INotificationsGroupedResponse }; 'i/notifications-grouped': { req: INotificationsGroupedRequest; res: INotificationsGroupedResponse };
'i/page-likes': { req: IPageLikesRequest; res: IPageLikesResponse }; 'i/page-likes': { req: IPageLikesRequest; res: IPageLikesResponse };
@ -823,40 +841,34 @@ export type Endpoints = {
'i/read-all-unread-notes': { req: EmptyRequest; res: EmptyResponse }; 'i/read-all-unread-notes': { req: EmptyRequest; res: EmptyResponse };
'i/read-announcement': { req: IReadAnnouncementRequest; res: EmptyResponse }; 'i/read-announcement': { req: IReadAnnouncementRequest; res: EmptyResponse };
'i/regenerate-token': { req: IRegenerateTokenRequest; res: EmptyResponse }; 'i/regenerate-token': { req: IRegenerateTokenRequest; res: EmptyResponse };
'i/registry/get': { req: IRegistryGetRequest; res: IRegistryGetResponse };
'i/registry/get-all': { req: IRegistryGetAllRequest; res: IRegistryGetAllResponse }; 'i/registry/get-all': { req: IRegistryGetAllRequest; res: IRegistryGetAllResponse };
'i/registry/get-detail': { req: IRegistryGetDetailRequest; res: IRegistryGetDetailResponse }; 'i/registry/get-detail': { req: IRegistryGetDetailRequest; res: IRegistryGetDetailResponse };
'i/registry/get': { req: IRegistryGetRequest; res: IRegistryGetResponse };
'i/registry/keys-with-type': { req: IRegistryKeysWithTypeRequest; res: IRegistryKeysWithTypeResponse };
'i/registry/keys': { req: IRegistryKeysRequest; res: IRegistryKeysResponse }; 'i/registry/keys': { req: IRegistryKeysRequest; res: IRegistryKeysResponse };
'i/registry/keys-with-type': { req: IRegistryKeysWithTypeRequest; res: IRegistryKeysWithTypeResponse };
'i/registry/remove': { req: IRegistryRemoveRequest; res: EmptyResponse }; 'i/registry/remove': { req: IRegistryRemoveRequest; res: EmptyResponse };
'i/registry/scopes-with-domain': { req: EmptyRequest; res: IRegistryScopesWithDomainResponse }; 'i/registry/scopes-with-domain': { req: EmptyRequest; res: IRegistryScopesWithDomainResponse };
'i/registry/set': { req: IRegistrySetRequest; res: EmptyResponse }; 'i/registry/set': { req: IRegistrySetRequest; res: EmptyResponse };
'i/revoke-token': { req: IRevokeTokenRequest; res: EmptyResponse }; 'i/revoke-token': { req: IRevokeTokenRequest; res: EmptyResponse };
'i/signin-history': { req: ISigninHistoryRequest; res: ISigninHistoryResponse }; 'i/signin-history': { req: ISigninHistoryRequest; res: ISigninHistoryResponse };
'i/unpin': { req: IUnpinRequest; res: IUnpinResponse }; 'i/unpin': { req: IUnpinRequest; res: IUnpinResponse };
'i/update-email': { req: IUpdateEmailRequest; res: IUpdateEmailResponse };
'i/update': { req: IUpdateRequest; res: IUpdateResponse }; 'i/update': { req: IUpdateRequest; res: IUpdateResponse };
'i/move': { req: IMoveRequest; res: IMoveResponse }; 'i/update-email': { req: IUpdateEmailRequest; res: IUpdateEmailResponse };
'i/webhooks/create': { req: IWebhooksCreateRequest; res: IWebhooksCreateResponse }; 'i/webhooks/create': { req: IWebhooksCreateRequest; res: IWebhooksCreateResponse };
'i/webhooks/delete': { req: IWebhooksDeleteRequest; res: EmptyResponse };
'i/webhooks/list': { req: EmptyRequest; res: IWebhooksListResponse }; 'i/webhooks/list': { req: EmptyRequest; res: IWebhooksListResponse };
'i/webhooks/show': { req: IWebhooksShowRequest; res: IWebhooksShowResponse }; 'i/webhooks/show': { req: IWebhooksShowRequest; res: IWebhooksShowResponse };
'i/webhooks/update': { req: IWebhooksUpdateRequest; res: EmptyResponse };
'i/webhooks/delete': { req: IWebhooksDeleteRequest; res: EmptyResponse };
'i/webhooks/test': { req: IWebhooksTestRequest; res: EmptyResponse }; 'i/webhooks/test': { req: IWebhooksTestRequest; res: EmptyResponse };
'i/webhooks/update': { req: IWebhooksUpdateRequest; res: EmptyResponse };
'invite/create': { req: EmptyRequest; res: InviteCreateResponse }; 'invite/create': { req: EmptyRequest; res: InviteCreateResponse };
'invite/delete': { req: InviteDeleteRequest; res: EmptyResponse }; 'invite/delete': { req: InviteDeleteRequest; res: EmptyResponse };
'invite/list': { req: InviteListRequest; res: InviteListResponse };
'invite/limit': { req: EmptyRequest; res: InviteLimitResponse }; 'invite/limit': { req: EmptyRequest; res: InviteLimitResponse };
'invite/list': { req: InviteListRequest; res: InviteListResponse };
'meta': { req: MetaRequest; res: MetaResponse }; 'meta': { req: MetaRequest; res: MetaResponse };
'emojis': { req: EmptyRequest; res: EmojisResponse };
'emoji': { req: EmojiRequest; res: EmojiResponse };
'miauth/gen-token': { req: MiauthGenTokenRequest; res: MiauthGenTokenResponse }; 'miauth/gen-token': { req: MiauthGenTokenRequest; res: MiauthGenTokenResponse };
'mute/create': { req: MuteCreateRequest; res: EmptyResponse }; 'mute/create': { req: MuteCreateRequest; res: EmptyResponse };
'mute/delete': { req: MuteDeleteRequest; res: EmptyResponse }; 'mute/delete': { req: MuteDeleteRequest; res: EmptyResponse };
'mute/list': { req: MuteListRequest; res: MuteListResponse }; 'mute/list': { req: MuteListRequest; res: MuteListResponse };
'renote-mute/create': { req: RenoteMuteCreateRequest; res: EmptyResponse };
'renote-mute/delete': { req: RenoteMuteDeleteRequest; res: EmptyResponse };
'renote-mute/list': { req: RenoteMuteListRequest; res: RenoteMuteListResponse };
'my/apps': { req: MyAppsRequest; res: MyAppsResponse }; 'my/apps': { req: MyAppsRequest; res: MyAppsResponse };
'notes': { req: NotesRequest; res: NotesResponse }; 'notes': { req: NotesRequest; res: NotesResponse };
'notes/children': { req: NotesChildrenRequest; res: NotesChildrenResponse }; 'notes/children': { req: NotesChildrenRequest; res: NotesChildrenResponse };
@ -878,8 +890,8 @@ export type Endpoints = {
'notes/reactions/delete': { req: NotesReactionsDeleteRequest; res: EmptyResponse }; 'notes/reactions/delete': { req: NotesReactionsDeleteRequest; res: EmptyResponse };
'notes/renotes': { req: NotesRenotesRequest; res: NotesRenotesResponse }; 'notes/renotes': { req: NotesRenotesRequest; res: NotesRenotesResponse };
'notes/replies': { req: NotesRepliesRequest; res: NotesRepliesResponse }; 'notes/replies': { req: NotesRepliesRequest; res: NotesRepliesResponse };
'notes/search-by-tag': { req: NotesSearchByTagRequest; res: NotesSearchByTagResponse };
'notes/search': { req: NotesSearchRequest; res: NotesSearchResponse }; 'notes/search': { req: NotesSearchRequest; res: NotesSearchResponse };
'notes/search-by-tag': { req: NotesSearchByTagRequest; res: NotesSearchByTagResponse };
'notes/show': { req: NotesShowRequest; res: NotesShowResponse }; 'notes/show': { req: NotesShowRequest; res: NotesShowResponse };
'notes/state': { req: NotesStateRequest; res: NotesStateResponse }; 'notes/state': { req: NotesStateRequest; res: NotesStateResponse };
'notes/thread-muting/create': { req: NotesThreadMutingCreateRequest; res: EmptyResponse }; 'notes/thread-muting/create': { req: NotesThreadMutingCreateRequest; res: EmptyResponse };
@ -900,76 +912,67 @@ export type Endpoints = {
'pages/show': { req: PagesShowRequest; res: PagesShowResponse }; 'pages/show': { req: PagesShowRequest; res: PagesShowResponse };
'pages/unlike': { req: PagesUnlikeRequest; res: EmptyResponse }; 'pages/unlike': { req: PagesUnlikeRequest; res: EmptyResponse };
'pages/update': { req: PagesUpdateRequest; res: EmptyResponse }; 'pages/update': { req: PagesUpdateRequest; res: EmptyResponse };
'flash/create': { req: FlashCreateRequest; res: FlashCreateResponse };
'flash/delete': { req: FlashDeleteRequest; res: EmptyResponse };
'flash/featured': { req: FlashFeaturedRequest; res: FlashFeaturedResponse };
'flash/like': { req: FlashLikeRequest; res: EmptyResponse };
'flash/show': { req: FlashShowRequest; res: FlashShowResponse };
'flash/unlike': { req: FlashUnlikeRequest; res: EmptyResponse };
'flash/update': { req: FlashUpdateRequest; res: EmptyResponse };
'flash/my': { req: FlashMyRequest; res: FlashMyResponse };
'flash/my-likes': { req: FlashMyLikesRequest; res: FlashMyLikesResponse };
'ping': { req: EmptyRequest; res: PingResponse }; 'ping': { req: EmptyRequest; res: PingResponse };
'pinned-users': { req: EmptyRequest; res: PinnedUsersResponse }; 'pinned-users': { req: EmptyRequest; res: PinnedUsersResponse };
'promo/read': { req: PromoReadRequest; res: EmptyResponse }; 'promo/read': { req: PromoReadRequest; res: EmptyResponse };
'roles/list': { req: EmptyRequest; res: RolesListResponse }; 'renote-mute/create': { req: RenoteMuteCreateRequest; res: EmptyResponse };
'roles/show': { req: RolesShowRequest; res: RolesShowResponse }; 'renote-mute/delete': { req: RenoteMuteDeleteRequest; res: EmptyResponse };
'roles/users': { req: RolesUsersRequest; res: RolesUsersResponse }; 'renote-mute/list': { req: RenoteMuteListRequest; res: RenoteMuteListResponse };
'roles/notes': { req: RolesNotesRequest; res: RolesNotesResponse };
'request-reset-password': { req: RequestResetPasswordRequest; res: EmptyResponse }; 'request-reset-password': { req: RequestResetPasswordRequest; res: EmptyResponse };
'reset-db': { req: EmptyRequest; res: EmptyResponse }; 'reset-db': { req: EmptyRequest; res: EmptyResponse };
'reset-password': { req: ResetPasswordRequest; res: EmptyResponse }; 'reset-password': { req: ResetPasswordRequest; res: EmptyResponse };
'retention': { req: EmptyRequest; res: RetentionResponse };
'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: EmptyResponse };
'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse };
'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse };
'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse };
'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse };
'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse };
'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse };
'roles/list': { req: EmptyRequest; res: RolesListResponse };
'roles/notes': { req: RolesNotesRequest; res: RolesNotesResponse };
'roles/show': { req: RolesShowRequest; res: RolesShowResponse };
'roles/users': { req: RolesUsersRequest; res: RolesUsersResponse };
'server-info': { req: EmptyRequest; res: ServerInfoResponse }; 'server-info': { req: EmptyRequest; res: ServerInfoResponse };
'stats': { req: EmptyRequest; res: StatsResponse }; 'stats': { req: EmptyRequest; res: StatsResponse };
'sw/show-registration': { req: SwShowRegistrationRequest; res: SwShowRegistrationResponse };
'sw/update-registration': { req: SwUpdateRegistrationRequest; res: SwUpdateRegistrationResponse };
'sw/register': { req: SwRegisterRequest; res: SwRegisterResponse }; 'sw/register': { req: SwRegisterRequest; res: SwRegisterResponse };
'sw/show-registration': { req: SwShowRegistrationRequest; res: SwShowRegistrationResponse };
'sw/unregister': { req: SwUnregisterRequest; res: EmptyResponse }; 'sw/unregister': { req: SwUnregisterRequest; res: EmptyResponse };
'sw/update-registration': { req: SwUpdateRegistrationRequest; res: SwUpdateRegistrationResponse };
'test': { req: TestRequest; res: TestResponse }; 'test': { req: TestRequest; res: TestResponse };
'username/available': { req: UsernameAvailableRequest; res: UsernameAvailableResponse }; 'username/available': { req: UsernameAvailableRequest; res: UsernameAvailableResponse };
'users': { req: UsersRequest; res: UsersResponse }; 'users': { req: UsersRequest; res: UsersResponse };
'users/achievements': { req: UsersAchievementsRequest; res: UsersAchievementsResponse };
'users/clips': { req: UsersClipsRequest; res: UsersClipsResponse }; 'users/clips': { req: UsersClipsRequest; res: UsersClipsResponse };
'users/featured-notes': { req: UsersFeaturedNotesRequest; res: UsersFeaturedNotesResponse };
'users/flashs': { req: UsersFlashsRequest; res: UsersFlashsResponse };
'users/followers': { req: UsersFollowersRequest; res: UsersFollowersResponse }; 'users/followers': { req: UsersFollowersRequest; res: UsersFollowersResponse };
'users/following': { req: UsersFollowingRequest; res: UsersFollowingResponse }; 'users/following': { req: UsersFollowingRequest; res: UsersFollowingResponse };
'users/gallery/posts': { req: UsersGalleryPostsRequest; res: UsersGalleryPostsResponse }; 'users/gallery/posts': { req: UsersGalleryPostsRequest; res: UsersGalleryPostsResponse };
'users/get-frequently-replied-users': { req: UsersGetFrequentlyRepliedUsersRequest; res: UsersGetFrequentlyRepliedUsersResponse }; 'users/get-frequently-replied-users': { req: UsersGetFrequentlyRepliedUsersRequest; res: UsersGetFrequentlyRepliedUsersResponse };
'users/featured-notes': { req: UsersFeaturedNotesRequest; res: UsersFeaturedNotesResponse };
'users/lists/create': { req: UsersListsCreateRequest; res: UsersListsCreateResponse }; 'users/lists/create': { req: UsersListsCreateRequest; res: UsersListsCreateResponse };
'users/lists/create-from-public': { req: UsersListsCreateFromPublicRequest; res: UsersListsCreateFromPublicResponse };
'users/lists/delete': { req: UsersListsDeleteRequest; res: EmptyResponse }; 'users/lists/delete': { req: UsersListsDeleteRequest; res: EmptyResponse };
'users/lists/favorite': { req: UsersListsFavoriteRequest; res: EmptyResponse };
'users/lists/get-memberships': { req: UsersListsGetMembershipsRequest; res: UsersListsGetMembershipsResponse };
'users/lists/list': { req: UsersListsListRequest; res: UsersListsListResponse }; 'users/lists/list': { req: UsersListsListRequest; res: UsersListsListResponse };
'users/lists/pull': { req: UsersListsPullRequest; res: EmptyResponse }; 'users/lists/pull': { req: UsersListsPullRequest; res: EmptyResponse };
'users/lists/push': { req: UsersListsPushRequest; res: EmptyResponse }; 'users/lists/push': { req: UsersListsPushRequest; res: EmptyResponse };
'users/lists/show': { req: UsersListsShowRequest; res: UsersListsShowResponse }; 'users/lists/show': { req: UsersListsShowRequest; res: UsersListsShowResponse };
'users/lists/favorite': { req: UsersListsFavoriteRequest; res: EmptyResponse };
'users/lists/unfavorite': { req: UsersListsUnfavoriteRequest; res: EmptyResponse }; 'users/lists/unfavorite': { req: UsersListsUnfavoriteRequest; res: EmptyResponse };
'users/lists/update': { req: UsersListsUpdateRequest; res: UsersListsUpdateResponse }; 'users/lists/update': { req: UsersListsUpdateRequest; res: UsersListsUpdateResponse };
'users/lists/create-from-public': { req: UsersListsCreateFromPublicRequest; res: UsersListsCreateFromPublicResponse };
'users/lists/update-membership': { req: UsersListsUpdateMembershipRequest; res: EmptyResponse }; 'users/lists/update-membership': { req: UsersListsUpdateMembershipRequest; res: EmptyResponse };
'users/lists/get-memberships': { req: UsersListsGetMembershipsRequest; res: UsersListsGetMembershipsResponse };
'users/notes': { req: UsersNotesRequest; res: UsersNotesResponse }; 'users/notes': { req: UsersNotesRequest; res: UsersNotesResponse };
'users/pages': { req: UsersPagesRequest; res: UsersPagesResponse }; 'users/pages': { req: UsersPagesRequest; res: UsersPagesResponse };
'users/flashs': { req: UsersFlashsRequest; res: UsersFlashsResponse };
'users/reactions': { req: UsersReactionsRequest; res: UsersReactionsResponse }; 'users/reactions': { req: UsersReactionsRequest; res: UsersReactionsResponse };
'users/recommendation': { req: UsersRecommendationRequest; res: UsersRecommendationResponse }; 'users/recommendation': { req: UsersRecommendationRequest; res: UsersRecommendationResponse };
'users/relation': { req: UsersRelationRequest; res: UsersRelationResponse }; 'users/relation': { req: UsersRelationRequest; res: UsersRelationResponse };
'users/report-abuse': { req: UsersReportAbuseRequest; res: EmptyResponse }; 'users/report-abuse': { req: UsersReportAbuseRequest; res: EmptyResponse };
'users/search-by-username-and-host': { req: UsersSearchByUsernameAndHostRequest; res: UsersSearchByUsernameAndHostResponse };
'users/search': { req: UsersSearchRequest; res: UsersSearchResponse }; 'users/search': { req: UsersSearchRequest; res: UsersSearchResponse };
'users/search-by-username-and-host': { req: UsersSearchByUsernameAndHostRequest; res: UsersSearchByUsernameAndHostResponse };
'users/show': { req: UsersShowRequest; res: UsersShowResponse }; 'users/show': { req: UsersShowRequest; res: UsersShowResponse };
'users/achievements': { req: UsersAchievementsRequest; res: UsersAchievementsResponse };
'users/update-memo': { req: UsersUpdateMemoRequest; res: EmptyResponse }; 'users/update-memo': { req: UsersUpdateMemoRequest; res: EmptyResponse };
'fetch-rss': { req: FetchRssRequest; res: FetchRssResponse }; 'v2/admin/emoji/list': { req: V2AdminEmojiListRequest; res: V2AdminEmojiListResponse };
'fetch-external-resources': { req: FetchExternalResourcesRequest; res: FetchExternalResourcesResponse };
'retention': { req: EmptyRequest; res: RetentionResponse };
'bubble-game/register': { req: BubbleGameRegisterRequest; res: EmptyResponse };
'bubble-game/ranking': { req: BubbleGameRankingRequest; res: BubbleGameRankingResponse };
'reversi/cancel-match': { req: ReversiCancelMatchRequest; res: EmptyResponse };
'reversi/games': { req: ReversiGamesRequest; res: ReversiGamesResponse };
'reversi/match': { req: ReversiMatchRequest; res: ReversiMatchResponse };
'reversi/invitations': { req: EmptyRequest; res: ReversiInvitationsResponse };
'reversi/show-game': { req: ReversiShowGameRequest; res: ReversiShowGameResponse };
'reversi/surrender': { req: ReversiSurrenderRequest; res: EmptyResponse };
'reversi/verify': { req: ReversiVerifyRequest; res: ReversiVerifyResponse };
} }
/** /**

View File

@ -4,18 +4,17 @@ import { operations } from './types.js';
export type EmptyRequest = Record<string, unknown> | undefined; export type EmptyRequest = Record<string, unknown> | undefined;
export type EmptyResponse = Record<string, unknown> | undefined; export type EmptyResponse = Record<string, unknown> | undefined;
export type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json']; export type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json'];
export type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json'];
export type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json']; export type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; export type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; export type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; export type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; export type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json'];
export type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; export type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json'];
export type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json'];
export type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json']; export type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json'];
export type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json']; export type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json'];
export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json'];
@ -41,25 +40,24 @@ export type AdminAvatarDecorationsListResponse = operations['admin___avatar-deco
export type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json']; export type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json'];
export type AdminCaptchaCurrentResponse = operations['admin___captcha___current']['responses']['200']['content']['application/json']; export type AdminCaptchaCurrentResponse = operations['admin___captcha___current']['responses']['200']['content']['application/json'];
export type AdminCaptchaSaveRequest = operations['admin___captcha___save']['requestBody']['content']['application/json']; export type AdminCaptchaSaveRequest = operations['admin___captcha___save']['requestBody']['content']['application/json'];
export type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json'];
export type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json']; export type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json'];
export type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json'];
export type AdminUnsetUserBannerRequest = operations['admin___unset-user-banner']['requestBody']['content']['application/json'];
export type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json']; export type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json'];
export type AdminDriveFilesResponse = operations['admin___drive___files']['responses']['200']['content']['application/json']; export type AdminDriveFilesResponse = operations['admin___drive___files']['responses']['200']['content']['application/json'];
export type AdminDriveShowFileRequest = operations['admin___drive___show-file']['requestBody']['content']['application/json']; export type AdminDriveShowFileRequest = operations['admin___drive___show-file']['requestBody']['content']['application/json'];
export type AdminDriveShowFileResponse = operations['admin___drive___show-file']['responses']['200']['content']['application/json']; export type AdminDriveShowFileResponse = operations['admin___drive___show-file']['responses']['200']['content']['application/json'];
export type AdminEmojiAddAliasesBulkRequest = operations['admin___emoji___add-aliases-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiAddRequest = operations['admin___emoji___add']['requestBody']['content']['application/json']; export type AdminEmojiAddRequest = operations['admin___emoji___add']['requestBody']['content']['application/json'];
export type AdminEmojiAddResponse = operations['admin___emoji___add']['responses']['200']['content']['application/json']; export type AdminEmojiAddResponse = operations['admin___emoji___add']['responses']['200']['content']['application/json'];
export type AdminEmojiAddAliasesBulkRequest = operations['admin___emoji___add-aliases-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiCopyRequest = operations['admin___emoji___copy']['requestBody']['content']['application/json']; export type AdminEmojiCopyRequest = operations['admin___emoji___copy']['requestBody']['content']['application/json'];
export type AdminEmojiCopyResponse = operations['admin___emoji___copy']['responses']['200']['content']['application/json']; export type AdminEmojiCopyResponse = operations['admin___emoji___copy']['responses']['200']['content']['application/json'];
export type AdminEmojiDeleteBulkRequest = operations['admin___emoji___delete-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiDeleteRequest = operations['admin___emoji___delete']['requestBody']['content']['application/json']; export type AdminEmojiDeleteRequest = operations['admin___emoji___delete']['requestBody']['content']['application/json'];
export type AdminEmojiDeleteBulkRequest = operations['admin___emoji___delete-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiImportZipRequest = operations['admin___emoji___import-zip']['requestBody']['content']['application/json']; export type AdminEmojiImportZipRequest = operations['admin___emoji___import-zip']['requestBody']['content']['application/json'];
export type AdminEmojiListRemoteRequest = operations['admin___emoji___list-remote']['requestBody']['content']['application/json'];
export type AdminEmojiListRemoteResponse = operations['admin___emoji___list-remote']['responses']['200']['content']['application/json'];
export type AdminEmojiListRequest = operations['admin___emoji___list']['requestBody']['content']['application/json']; export type AdminEmojiListRequest = operations['admin___emoji___list']['requestBody']['content']['application/json'];
export type AdminEmojiListResponse = operations['admin___emoji___list']['responses']['200']['content']['application/json']; export type AdminEmojiListResponse = operations['admin___emoji___list']['responses']['200']['content']['application/json'];
export type AdminEmojiListRemoteRequest = operations['admin___emoji___list-remote']['requestBody']['content']['application/json'];
export type AdminEmojiListRemoteResponse = operations['admin___emoji___list-remote']['responses']['200']['content']['application/json'];
export type AdminEmojiRemoveAliasesBulkRequest = operations['admin___emoji___remove-aliases-bulk']['requestBody']['content']['application/json']; export type AdminEmojiRemoveAliasesBulkRequest = operations['admin___emoji___remove-aliases-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiSetAliasesBulkRequest = operations['admin___emoji___set-aliases-bulk']['requestBody']['content']['application/json']; export type AdminEmojiSetAliasesBulkRequest = operations['admin___emoji___set-aliases-bulk']['requestBody']['content']['application/json'];
export type AdminEmojiSetCategoryBulkRequest = operations['admin___emoji___set-category-bulk']['requestBody']['content']['application/json']; export type AdminEmojiSetCategoryBulkRequest = operations['admin___emoji___set-category-bulk']['requestBody']['content']['application/json'];
@ -69,6 +67,7 @@ export type AdminFederationDeleteAllFilesRequest = operations['admin___federatio
export type AdminFederationRefreshRemoteInstanceMetadataRequest = operations['admin___federation___refresh-remote-instance-metadata']['requestBody']['content']['application/json']; export type AdminFederationRefreshRemoteInstanceMetadataRequest = operations['admin___federation___refresh-remote-instance-metadata']['requestBody']['content']['application/json'];
export type AdminFederationRemoveAllFollowingRequest = operations['admin___federation___remove-all-following']['requestBody']['content']['application/json']; export type AdminFederationRemoveAllFollowingRequest = operations['admin___federation___remove-all-following']['requestBody']['content']['application/json'];
export type AdminFederationUpdateInstanceRequest = operations['admin___federation___update-instance']['requestBody']['content']['application/json']; export type AdminFederationUpdateInstanceRequest = operations['admin___federation___update-instance']['requestBody']['content']['application/json'];
export type AdminForwardAbuseUserReportRequest = operations['admin___forward-abuse-user-report']['requestBody']['content']['application/json'];
export type AdminGetIndexStatsResponse = operations['admin___get-index-stats']['responses']['200']['content']['application/json']; export type AdminGetIndexStatsResponse = operations['admin___get-index-stats']['responses']['200']['content']['application/json'];
export type AdminGetTableStatsResponse = operations['admin___get-table-stats']['responses']['200']['content']['application/json']; export type AdminGetTableStatsResponse = operations['admin___get-table-stats']['responses']['200']['content']['application/json'];
export type AdminGetUserIpsRequest = operations['admin___get-user-ips']['requestBody']['content']['application/json']; export type AdminGetUserIpsRequest = operations['admin___get-user-ips']['requestBody']['content']['application/json'];
@ -77,6 +76,7 @@ export type AdminInviteCreateRequest = operations['admin___invite___create']['re
export type AdminInviteCreateResponse = operations['admin___invite___create']['responses']['200']['content']['application/json']; export type AdminInviteCreateResponse = operations['admin___invite___create']['responses']['200']['content']['application/json'];
export type AdminInviteListRequest = operations['admin___invite___list']['requestBody']['content']['application/json']; export type AdminInviteListRequest = operations['admin___invite___list']['requestBody']['content']['application/json'];
export type AdminInviteListResponse = operations['admin___invite___list']['responses']['200']['content']['application/json']; export type AdminInviteListResponse = operations['admin___invite___list']['responses']['200']['content']['application/json'];
export type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json'];
export type AdminPromoCreateRequest = operations['admin___promo___create']['requestBody']['content']['application/json']; export type AdminPromoCreateRequest = operations['admin___promo___create']['requestBody']['content']['application/json'];
export type AdminQueueDeliverDelayedResponse = operations['admin___queue___deliver-delayed']['responses']['200']['content']['application/json']; export type AdminQueueDeliverDelayedResponse = operations['admin___queue___deliver-delayed']['responses']['200']['content']['application/json'];
export type AdminQueueInboxDelayedResponse = operations['admin___queue___inbox-delayed']['responses']['200']['content']['application/json']; export type AdminQueueInboxDelayedResponse = operations['admin___queue___inbox-delayed']['responses']['200']['content']['application/json'];
@ -89,8 +89,18 @@ export type AdminRelaysRemoveRequest = operations['admin___relays___remove']['re
export type AdminResetPasswordRequest = operations['admin___reset-password']['requestBody']['content']['application/json']; export type AdminResetPasswordRequest = operations['admin___reset-password']['requestBody']['content']['application/json'];
export type AdminResetPasswordResponse = operations['admin___reset-password']['responses']['200']['content']['application/json']; export type AdminResetPasswordResponse = operations['admin___reset-password']['responses']['200']['content']['application/json'];
export type AdminResolveAbuseUserReportRequest = operations['admin___resolve-abuse-user-report']['requestBody']['content']['application/json']; export type AdminResolveAbuseUserReportRequest = operations['admin___resolve-abuse-user-report']['requestBody']['content']['application/json'];
export type AdminForwardAbuseUserReportRequest = operations['admin___forward-abuse-user-report']['requestBody']['content']['application/json']; export type AdminRolesAssignRequest = operations['admin___roles___assign']['requestBody']['content']['application/json'];
export type AdminUpdateAbuseUserReportRequest = operations['admin___update-abuse-user-report']['requestBody']['content']['application/json']; export type AdminRolesCreateRequest = operations['admin___roles___create']['requestBody']['content']['application/json'];
export type AdminRolesCreateResponse = operations['admin___roles___create']['responses']['200']['content']['application/json'];
export type AdminRolesDeleteRequest = operations['admin___roles___delete']['requestBody']['content']['application/json'];
export type AdminRolesListResponse = operations['admin___roles___list']['responses']['200']['content']['application/json'];
export type AdminRolesShowRequest = operations['admin___roles___show']['requestBody']['content']['application/json'];
export type AdminRolesShowResponse = operations['admin___roles___show']['responses']['200']['content']['application/json'];
export type AdminRolesUnassignRequest = operations['admin___roles___unassign']['requestBody']['content']['application/json'];
export type AdminRolesUpdateRequest = operations['admin___roles___update']['requestBody']['content']['application/json'];
export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json'];
export type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json'];
export type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json'];
export type AdminSendEmailRequest = operations['admin___send-email']['requestBody']['content']['application/json']; export type AdminSendEmailRequest = operations['admin___send-email']['requestBody']['content']['application/json'];
export type AdminServerInfoResponse = operations['admin___server-info']['responses']['200']['content']['application/json']; export type AdminServerInfoResponse = operations['admin___server-info']['responses']['200']['content']['application/json'];
export type AdminShowModerationLogsRequest = operations['admin___show-moderation-logs']['requestBody']['content']['application/json']; export type AdminShowModerationLogsRequest = operations['admin___show-moderation-logs']['requestBody']['content']['application/json'];
@ -100,22 +110,6 @@ export type AdminShowUserResponse = operations['admin___show-user']['responses']
export type AdminShowUsersRequest = operations['admin___show-users']['requestBody']['content']['application/json']; export type AdminShowUsersRequest = operations['admin___show-users']['requestBody']['content']['application/json'];
export type AdminShowUsersResponse = operations['admin___show-users']['responses']['200']['content']['application/json']; export type AdminShowUsersResponse = operations['admin___show-users']['responses']['200']['content']['application/json'];
export type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; export type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json'];
export type AdminUnsuspendUserRequest = operations['admin___unsuspend-user']['requestBody']['content']['application/json'];
export type AdminUpdateMetaRequest = operations['admin___update-meta']['requestBody']['content']['application/json'];
export type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json'];
export type AdminUpdateUserNoteRequest = operations['admin___update-user-note']['requestBody']['content']['application/json'];
export type AdminRolesCreateRequest = operations['admin___roles___create']['requestBody']['content']['application/json'];
export type AdminRolesCreateResponse = operations['admin___roles___create']['responses']['200']['content']['application/json'];
export type AdminRolesDeleteRequest = operations['admin___roles___delete']['requestBody']['content']['application/json'];
export type AdminRolesListResponse = operations['admin___roles___list']['responses']['200']['content']['application/json'];
export type AdminRolesShowRequest = operations['admin___roles___show']['requestBody']['content']['application/json'];
export type AdminRolesShowResponse = operations['admin___roles___show']['responses']['200']['content']['application/json'];
export type AdminRolesUpdateRequest = operations['admin___roles___update']['requestBody']['content']['application/json'];
export type AdminRolesAssignRequest = operations['admin___roles___assign']['requestBody']['content']['application/json'];
export type AdminRolesUnassignRequest = operations['admin___roles___unassign']['requestBody']['content']['application/json'];
export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json'];
export type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json'];
export type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json'];
export type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; export type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json'];
export type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; export type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json'];
export type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; export type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json'];
@ -123,9 +117,15 @@ export type AdminSystemWebhookListRequest = operations['admin___system-webhook__
export type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; export type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json'];
export type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; export type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json'];
export type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; export type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json'];
export type AdminSystemWebhookTestRequest = operations['admin___system-webhook___test']['requestBody']['content']['application/json'];
export type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; export type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json'];
export type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; export type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json'];
export type AdminSystemWebhookTestRequest = operations['admin___system-webhook___test']['requestBody']['content']['application/json']; export type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json'];
export type AdminUnsetUserBannerRequest = operations['admin___unset-user-banner']['requestBody']['content']['application/json'];
export type AdminUnsuspendUserRequest = operations['admin___unsuspend-user']['requestBody']['content']['application/json'];
export type AdminUpdateAbuseUserReportRequest = operations['admin___update-abuse-user-report']['requestBody']['content']['application/json'];
export type AdminUpdateMetaRequest = operations['admin___update-meta']['requestBody']['content']['application/json'];
export type AdminUpdateUserNoteRequest = operations['admin___update-user-note']['requestBody']['content']['application/json'];
export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json']; export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json'];
export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json']; export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json'];
export type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json']; export type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json'];
@ -161,26 +161,29 @@ export type BlockingDeleteRequest = operations['blocking___delete']['requestBody
export type BlockingDeleteResponse = operations['blocking___delete']['responses']['200']['content']['application/json']; export type BlockingDeleteResponse = operations['blocking___delete']['responses']['200']['content']['application/json'];
export type BlockingListRequest = operations['blocking___list']['requestBody']['content']['application/json']; export type BlockingListRequest = operations['blocking___list']['requestBody']['content']['application/json'];
export type BlockingListResponse = operations['blocking___list']['responses']['200']['content']['application/json']; export type BlockingListResponse = operations['blocking___list']['responses']['200']['content']['application/json'];
export type BubbleGameRankingRequest = operations['bubble-game___ranking']['requestBody']['content']['application/json'];
export type BubbleGameRankingResponse = operations['bubble-game___ranking']['responses']['200']['content']['application/json'];
export type BubbleGameRegisterRequest = operations['bubble-game___register']['requestBody']['content']['application/json'];
export type ChannelsCreateRequest = operations['channels___create']['requestBody']['content']['application/json']; export type ChannelsCreateRequest = operations['channels___create']['requestBody']['content']['application/json'];
export type ChannelsCreateResponse = operations['channels___create']['responses']['200']['content']['application/json']; export type ChannelsCreateResponse = operations['channels___create']['responses']['200']['content']['application/json'];
export type ChannelsFavoriteRequest = operations['channels___favorite']['requestBody']['content']['application/json'];
export type ChannelsFeaturedResponse = operations['channels___featured']['responses']['200']['content']['application/json']; export type ChannelsFeaturedResponse = operations['channels___featured']['responses']['200']['content']['application/json'];
export type ChannelsFollowRequest = operations['channels___follow']['requestBody']['content']['application/json']; export type ChannelsFollowRequest = operations['channels___follow']['requestBody']['content']['application/json'];
export type ChannelsFollowedRequest = operations['channels___followed']['requestBody']['content']['application/json']; export type ChannelsFollowedRequest = operations['channels___followed']['requestBody']['content']['application/json'];
export type ChannelsFollowedResponse = operations['channels___followed']['responses']['200']['content']['application/json']; export type ChannelsFollowedResponse = operations['channels___followed']['responses']['200']['content']['application/json'];
export type ChannelsMyFavoritesResponse = operations['channels___my-favorites']['responses']['200']['content']['application/json'];
export type ChannelsOwnedRequest = operations['channels___owned']['requestBody']['content']['application/json']; export type ChannelsOwnedRequest = operations['channels___owned']['requestBody']['content']['application/json'];
export type ChannelsOwnedResponse = operations['channels___owned']['responses']['200']['content']['application/json']; export type ChannelsOwnedResponse = operations['channels___owned']['responses']['200']['content']['application/json'];
export type ChannelsSearchRequest = operations['channels___search']['requestBody']['content']['application/json'];
export type ChannelsSearchResponse = operations['channels___search']['responses']['200']['content']['application/json'];
export type ChannelsShowRequest = operations['channels___show']['requestBody']['content']['application/json']; export type ChannelsShowRequest = operations['channels___show']['requestBody']['content']['application/json'];
export type ChannelsShowResponse = operations['channels___show']['responses']['200']['content']['application/json']; export type ChannelsShowResponse = operations['channels___show']['responses']['200']['content']['application/json'];
export type ChannelsTimelineRequest = operations['channels___timeline']['requestBody']['content']['application/json']; export type ChannelsTimelineRequest = operations['channels___timeline']['requestBody']['content']['application/json'];
export type ChannelsTimelineResponse = operations['channels___timeline']['responses']['200']['content']['application/json']; export type ChannelsTimelineResponse = operations['channels___timeline']['responses']['200']['content']['application/json'];
export type ChannelsUnfavoriteRequest = operations['channels___unfavorite']['requestBody']['content']['application/json'];
export type ChannelsUnfollowRequest = operations['channels___unfollow']['requestBody']['content']['application/json']; export type ChannelsUnfollowRequest = operations['channels___unfollow']['requestBody']['content']['application/json'];
export type ChannelsUpdateRequest = operations['channels___update']['requestBody']['content']['application/json']; export type ChannelsUpdateRequest = operations['channels___update']['requestBody']['content']['application/json'];
export type ChannelsUpdateResponse = operations['channels___update']['responses']['200']['content']['application/json']; export type ChannelsUpdateResponse = operations['channels___update']['responses']['200']['content']['application/json'];
export type ChannelsFavoriteRequest = operations['channels___favorite']['requestBody']['content']['application/json'];
export type ChannelsUnfavoriteRequest = operations['channels___unfavorite']['requestBody']['content']['application/json'];
export type ChannelsMyFavoritesResponse = operations['channels___my-favorites']['responses']['200']['content']['application/json'];
export type ChannelsSearchRequest = operations['channels___search']['requestBody']['content']['application/json'];
export type ChannelsSearchResponse = operations['channels___search']['responses']['200']['content']['application/json'];
export type ChartsActiveUsersRequest = operations['charts___active-users']['requestBody']['content']['application/json']; export type ChartsActiveUsersRequest = operations['charts___active-users']['requestBody']['content']['application/json'];
export type ChartsActiveUsersResponse = operations['charts___active-users']['responses']['200']['content']['application/json']; export type ChartsActiveUsersResponse = operations['charts___active-users']['responses']['200']['content']['application/json'];
export type ChartsApRequestRequest = operations['charts___ap-request']['requestBody']['content']['application/json']; export type ChartsApRequestRequest = operations['charts___ap-request']['requestBody']['content']['application/json'];
@ -206,20 +209,20 @@ export type ChartsUserReactionsResponse = operations['charts___user___reactions'
export type ChartsUsersRequest = operations['charts___users']['requestBody']['content']['application/json']; export type ChartsUsersRequest = operations['charts___users']['requestBody']['content']['application/json'];
export type ChartsUsersResponse = operations['charts___users']['responses']['200']['content']['application/json']; export type ChartsUsersResponse = operations['charts___users']['responses']['200']['content']['application/json'];
export type ClipsAddNoteRequest = operations['clips___add-note']['requestBody']['content']['application/json']; export type ClipsAddNoteRequest = operations['clips___add-note']['requestBody']['content']['application/json'];
export type ClipsRemoveNoteRequest = operations['clips___remove-note']['requestBody']['content']['application/json'];
export type ClipsCreateRequest = operations['clips___create']['requestBody']['content']['application/json']; export type ClipsCreateRequest = operations['clips___create']['requestBody']['content']['application/json'];
export type ClipsCreateResponse = operations['clips___create']['responses']['200']['content']['application/json']; export type ClipsCreateResponse = operations['clips___create']['responses']['200']['content']['application/json'];
export type ClipsDeleteRequest = operations['clips___delete']['requestBody']['content']['application/json']; export type ClipsDeleteRequest = operations['clips___delete']['requestBody']['content']['application/json'];
export type ClipsFavoriteRequest = operations['clips___favorite']['requestBody']['content']['application/json'];
export type ClipsListResponse = operations['clips___list']['responses']['200']['content']['application/json']; export type ClipsListResponse = operations['clips___list']['responses']['200']['content']['application/json'];
export type ClipsMyFavoritesResponse = operations['clips___my-favorites']['responses']['200']['content']['application/json'];
export type ClipsNotesRequest = operations['clips___notes']['requestBody']['content']['application/json']; export type ClipsNotesRequest = operations['clips___notes']['requestBody']['content']['application/json'];
export type ClipsNotesResponse = operations['clips___notes']['responses']['200']['content']['application/json']; export type ClipsNotesResponse = operations['clips___notes']['responses']['200']['content']['application/json'];
export type ClipsRemoveNoteRequest = operations['clips___remove-note']['requestBody']['content']['application/json'];
export type ClipsShowRequest = operations['clips___show']['requestBody']['content']['application/json']; export type ClipsShowRequest = operations['clips___show']['requestBody']['content']['application/json'];
export type ClipsShowResponse = operations['clips___show']['responses']['200']['content']['application/json']; export type ClipsShowResponse = operations['clips___show']['responses']['200']['content']['application/json'];
export type ClipsUnfavoriteRequest = operations['clips___unfavorite']['requestBody']['content']['application/json'];
export type ClipsUpdateRequest = operations['clips___update']['requestBody']['content']['application/json']; export type ClipsUpdateRequest = operations['clips___update']['requestBody']['content']['application/json'];
export type ClipsUpdateResponse = operations['clips___update']['responses']['200']['content']['application/json']; export type ClipsUpdateResponse = operations['clips___update']['responses']['200']['content']['application/json'];
export type ClipsFavoriteRequest = operations['clips___favorite']['requestBody']['content']['application/json'];
export type ClipsUnfavoriteRequest = operations['clips___unfavorite']['requestBody']['content']['application/json'];
export type ClipsMyFavoritesResponse = operations['clips___my-favorites']['responses']['200']['content']['application/json'];
export type DriveResponse = operations['drive']['responses']['200']['content']['application/json']; export type DriveResponse = operations['drive']['responses']['200']['content']['application/json'];
export type DriveFilesRequest = operations['drive___files']['requestBody']['content']['application/json']; export type DriveFilesRequest = operations['drive___files']['requestBody']['content']['application/json'];
export type DriveFilesResponse = operations['drive___files']['responses']['200']['content']['application/json']; export type DriveFilesResponse = operations['drive___files']['responses']['200']['content']['application/json'];
@ -230,10 +233,10 @@ export type DriveFilesCheckExistenceResponse = operations['drive___files___check
export type DriveFilesCreateRequest = operations['drive___files___create']['requestBody']['content']['multipart/form-data']; export type DriveFilesCreateRequest = operations['drive___files___create']['requestBody']['content']['multipart/form-data'];
export type DriveFilesCreateResponse = operations['drive___files___create']['responses']['200']['content']['application/json']; export type DriveFilesCreateResponse = operations['drive___files___create']['responses']['200']['content']['application/json'];
export type DriveFilesDeleteRequest = operations['drive___files___delete']['requestBody']['content']['application/json']; export type DriveFilesDeleteRequest = operations['drive___files___delete']['requestBody']['content']['application/json'];
export type DriveFilesFindByHashRequest = operations['drive___files___find-by-hash']['requestBody']['content']['application/json'];
export type DriveFilesFindByHashResponse = operations['drive___files___find-by-hash']['responses']['200']['content']['application/json'];
export type DriveFilesFindRequest = operations['drive___files___find']['requestBody']['content']['application/json']; export type DriveFilesFindRequest = operations['drive___files___find']['requestBody']['content']['application/json'];
export type DriveFilesFindResponse = operations['drive___files___find']['responses']['200']['content']['application/json']; export type DriveFilesFindResponse = operations['drive___files___find']['responses']['200']['content']['application/json'];
export type DriveFilesFindByHashRequest = operations['drive___files___find-by-hash']['requestBody']['content']['application/json'];
export type DriveFilesFindByHashResponse = operations['drive___files___find-by-hash']['responses']['200']['content']['application/json'];
export type DriveFilesShowRequest = operations['drive___files___show']['requestBody']['content']['application/json']; export type DriveFilesShowRequest = operations['drive___files___show']['requestBody']['content']['application/json'];
export type DriveFilesShowResponse = operations['drive___files___show']['responses']['200']['content']['application/json']; export type DriveFilesShowResponse = operations['drive___files___show']['responses']['200']['content']['application/json'];
export type DriveFilesUpdateRequest = operations['drive___files___update']['requestBody']['content']['application/json']; export type DriveFilesUpdateRequest = operations['drive___files___update']['requestBody']['content']['application/json'];
@ -254,6 +257,9 @@ export type DriveStreamRequest = operations['drive___stream']['requestBody']['co
export type DriveStreamResponse = operations['drive___stream']['responses']['200']['content']['application/json']; export type DriveStreamResponse = operations['drive___stream']['responses']['200']['content']['application/json'];
export type EmailAddressAvailableRequest = operations['email-address___available']['requestBody']['content']['application/json']; export type EmailAddressAvailableRequest = operations['email-address___available']['requestBody']['content']['application/json'];
export type EmailAddressAvailableResponse = operations['email-address___available']['responses']['200']['content']['application/json']; export type EmailAddressAvailableResponse = operations['email-address___available']['responses']['200']['content']['application/json'];
export type EmojiRequest = operations['emoji']['requestBody']['content']['application/json'];
export type EmojiResponse = operations['emoji']['responses']['200']['content']['application/json'];
export type EmojisResponse = operations['emojis']['responses']['200']['content']['application/json'];
export type EndpointRequest = operations['endpoint']['requestBody']['content']['application/json']; export type EndpointRequest = operations['endpoint']['requestBody']['content']['application/json'];
export type EndpointResponse = operations['endpoint']['responses']['200']['content']['application/json']; export type EndpointResponse = operations['endpoint']['responses']['200']['content']['application/json'];
export type EndpointsResponse = operations['endpoints']['responses']['200']['content']['application/json']; export type EndpointsResponse = operations['endpoints']['responses']['200']['content']['application/json'];
@ -265,18 +271,33 @@ export type FederationInstancesRequest = operations['federation___instances']['r
export type FederationInstancesResponse = operations['federation___instances']['responses']['200']['content']['application/json']; export type FederationInstancesResponse = operations['federation___instances']['responses']['200']['content']['application/json'];
export type FederationShowInstanceRequest = operations['federation___show-instance']['requestBody']['content']['application/json']; export type FederationShowInstanceRequest = operations['federation___show-instance']['requestBody']['content']['application/json'];
export type FederationShowInstanceResponse = operations['federation___show-instance']['responses']['200']['content']['application/json']; export type FederationShowInstanceResponse = operations['federation___show-instance']['responses']['200']['content']['application/json'];
export type FederationStatsRequest = operations['federation___stats']['requestBody']['content']['application/json'];
export type FederationStatsResponse = operations['federation___stats']['responses']['200']['content']['application/json'];
export type FederationUpdateRemoteUserRequest = operations['federation___update-remote-user']['requestBody']['content']['application/json']; export type FederationUpdateRemoteUserRequest = operations['federation___update-remote-user']['requestBody']['content']['application/json'];
export type FederationUsersRequest = operations['federation___users']['requestBody']['content']['application/json']; export type FederationUsersRequest = operations['federation___users']['requestBody']['content']['application/json'];
export type FederationUsersResponse = operations['federation___users']['responses']['200']['content']['application/json']; export type FederationUsersResponse = operations['federation___users']['responses']['200']['content']['application/json'];
export type FederationStatsRequest = operations['federation___stats']['requestBody']['content']['application/json']; export type FetchExternalResourcesRequest = operations['fetch-external-resources']['requestBody']['content']['application/json'];
export type FederationStatsResponse = operations['federation___stats']['responses']['200']['content']['application/json']; export type FetchExternalResourcesResponse = operations['fetch-external-resources']['responses']['200']['content']['application/json'];
export type FetchRssRequest = operations['fetch-rss']['requestBody']['content']['application/json'];
export type FetchRssResponse = operations['fetch-rss']['responses']['200']['content']['application/json'];
export type FlashCreateRequest = operations['flash___create']['requestBody']['content']['application/json'];
export type FlashCreateResponse = operations['flash___create']['responses']['200']['content']['application/json'];
export type FlashDeleteRequest = operations['flash___delete']['requestBody']['content']['application/json'];
export type FlashFeaturedRequest = operations['flash___featured']['requestBody']['content']['application/json'];
export type FlashFeaturedResponse = operations['flash___featured']['responses']['200']['content']['application/json'];
export type FlashLikeRequest = operations['flash___like']['requestBody']['content']['application/json'];
export type FlashMyRequest = operations['flash___my']['requestBody']['content']['application/json'];
export type FlashMyResponse = operations['flash___my']['responses']['200']['content']['application/json'];
export type FlashMyLikesRequest = operations['flash___my-likes']['requestBody']['content']['application/json'];
export type FlashMyLikesResponse = operations['flash___my-likes']['responses']['200']['content']['application/json'];
export type FlashShowRequest = operations['flash___show']['requestBody']['content']['application/json'];
export type FlashShowResponse = operations['flash___show']['responses']['200']['content']['application/json'];
export type FlashUnlikeRequest = operations['flash___unlike']['requestBody']['content']['application/json'];
export type FlashUpdateRequest = operations['flash___update']['requestBody']['content']['application/json'];
export type FollowingCreateRequest = operations['following___create']['requestBody']['content']['application/json']; export type FollowingCreateRequest = operations['following___create']['requestBody']['content']['application/json'];
export type FollowingCreateResponse = operations['following___create']['responses']['200']['content']['application/json']; export type FollowingCreateResponse = operations['following___create']['responses']['200']['content']['application/json'];
export type FollowingDeleteRequest = operations['following___delete']['requestBody']['content']['application/json']; export type FollowingDeleteRequest = operations['following___delete']['requestBody']['content']['application/json'];
export type FollowingDeleteResponse = operations['following___delete']['responses']['200']['content']['application/json']; export type FollowingDeleteResponse = operations['following___delete']['responses']['200']['content']['application/json'];
export type FollowingUpdateRequest = operations['following___update']['requestBody']['content']['application/json'];
export type FollowingUpdateResponse = operations['following___update']['responses']['200']['content']['application/json'];
export type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json'];
export type FollowingInvalidateRequest = operations['following___invalidate']['requestBody']['content']['application/json']; export type FollowingInvalidateRequest = operations['following___invalidate']['requestBody']['content']['application/json'];
export type FollowingInvalidateResponse = operations['following___invalidate']['responses']['200']['content']['application/json']; export type FollowingInvalidateResponse = operations['following___invalidate']['responses']['200']['content']['application/json'];
export type FollowingRequestsAcceptRequest = operations['following___requests___accept']['requestBody']['content']['application/json']; export type FollowingRequestsAcceptRequest = operations['following___requests___accept']['requestBody']['content']['application/json'];
@ -284,9 +305,12 @@ export type FollowingRequestsCancelRequest = operations['following___requests___
export type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json']; export type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json'];
export type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json']; export type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json'];
export type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json']; export type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json'];
export type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json'];
export type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json']; export type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json'];
export type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json']; export type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json'];
export type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json']; export type FollowingUpdateRequest = operations['following___update']['requestBody']['content']['application/json'];
export type FollowingUpdateResponse = operations['following___update']['responses']['200']['content']['application/json'];
export type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json'];
export type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json']; export type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json'];
export type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json']; export type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json'];
export type GalleryPopularResponse = operations['gallery___popular']['responses']['200']['content']['application/json']; export type GalleryPopularResponse = operations['gallery___popular']['responses']['200']['content']['application/json'];
@ -301,8 +325,8 @@ export type GalleryPostsShowResponse = operations['gallery___posts___show']['res
export type GalleryPostsUnlikeRequest = operations['gallery___posts___unlike']['requestBody']['content']['application/json']; export type GalleryPostsUnlikeRequest = operations['gallery___posts___unlike']['requestBody']['content']['application/json'];
export type GalleryPostsUpdateRequest = operations['gallery___posts___update']['requestBody']['content']['application/json']; export type GalleryPostsUpdateRequest = operations['gallery___posts___update']['requestBody']['content']['application/json'];
export type GalleryPostsUpdateResponse = operations['gallery___posts___update']['responses']['200']['content']['application/json']; export type GalleryPostsUpdateResponse = operations['gallery___posts___update']['responses']['200']['content']['application/json'];
export type GetOnlineUsersCountResponse = operations['get-online-users-count']['responses']['200']['content']['application/json'];
export type GetAvatarDecorationsResponse = operations['get-avatar-decorations']['responses']['200']['content']['application/json']; export type GetAvatarDecorationsResponse = operations['get-avatar-decorations']['responses']['200']['content']['application/json'];
export type GetOnlineUsersCountResponse = operations['get-online-users-count']['responses']['200']['content']['application/json'];
export type HashtagsListRequest = operations['hashtags___list']['requestBody']['content']['application/json']; export type HashtagsListRequest = operations['hashtags___list']['requestBody']['content']['application/json'];
export type HashtagsListResponse = operations['hashtags___list']['responses']['200']['content']['application/json']; export type HashtagsListResponse = operations['hashtags___list']['responses']['200']['content']['application/json'];
export type HashtagsSearchRequest = operations['hashtags___search']['requestBody']['content']['application/json']; export type HashtagsSearchRequest = operations['hashtags___search']['requestBody']['content']['application/json'];
@ -318,19 +342,19 @@ export type I2faDoneResponse = operations['i___2fa___done']['responses']['200'][
export type I2faKeyDoneRequest = operations['i___2fa___key-done']['requestBody']['content']['application/json']; export type I2faKeyDoneRequest = operations['i___2fa___key-done']['requestBody']['content']['application/json'];
export type I2faKeyDoneResponse = operations['i___2fa___key-done']['responses']['200']['content']['application/json']; export type I2faKeyDoneResponse = operations['i___2fa___key-done']['responses']['200']['content']['application/json'];
export type I2faPasswordLessRequest = operations['i___2fa___password-less']['requestBody']['content']['application/json']; export type I2faPasswordLessRequest = operations['i___2fa___password-less']['requestBody']['content']['application/json'];
export type I2faRegisterKeyRequest = operations['i___2fa___register-key']['requestBody']['content']['application/json'];
export type I2faRegisterKeyResponse = operations['i___2fa___register-key']['responses']['200']['content']['application/json'];
export type I2faRegisterRequest = operations['i___2fa___register']['requestBody']['content']['application/json']; export type I2faRegisterRequest = operations['i___2fa___register']['requestBody']['content']['application/json'];
export type I2faRegisterResponse = operations['i___2fa___register']['responses']['200']['content']['application/json']; export type I2faRegisterResponse = operations['i___2fa___register']['responses']['200']['content']['application/json'];
export type I2faUpdateKeyRequest = operations['i___2fa___update-key']['requestBody']['content']['application/json']; export type I2faRegisterKeyRequest = operations['i___2fa___register-key']['requestBody']['content']['application/json'];
export type I2faRegisterKeyResponse = operations['i___2fa___register-key']['responses']['200']['content']['application/json'];
export type I2faRemoveKeyRequest = operations['i___2fa___remove-key']['requestBody']['content']['application/json']; export type I2faRemoveKeyRequest = operations['i___2fa___remove-key']['requestBody']['content']['application/json'];
export type I2faUnregisterRequest = operations['i___2fa___unregister']['requestBody']['content']['application/json']; export type I2faUnregisterRequest = operations['i___2fa___unregister']['requestBody']['content']['application/json'];
export type I2faUpdateKeyRequest = operations['i___2fa___update-key']['requestBody']['content']['application/json'];
export type IAppsRequest = operations['i___apps']['requestBody']['content']['application/json']; export type IAppsRequest = operations['i___apps']['requestBody']['content']['application/json'];
export type IAppsResponse = operations['i___apps']['responses']['200']['content']['application/json']; export type IAppsResponse = operations['i___apps']['responses']['200']['content']['application/json'];
export type IAuthorizedAppsRequest = operations['i___authorized-apps']['requestBody']['content']['application/json']; export type IAuthorizedAppsRequest = operations['i___authorized-apps']['requestBody']['content']['application/json'];
export type IAuthorizedAppsResponse = operations['i___authorized-apps']['responses']['200']['content']['application/json']; export type IAuthorizedAppsResponse = operations['i___authorized-apps']['responses']['200']['content']['application/json'];
export type IClaimAchievementRequest = operations['i___claim-achievement']['requestBody']['content']['application/json'];
export type IChangePasswordRequest = operations['i___change-password']['requestBody']['content']['application/json']; export type IChangePasswordRequest = operations['i___change-password']['requestBody']['content']['application/json'];
export type IClaimAchievementRequest = operations['i___claim-achievement']['requestBody']['content']['application/json'];
export type IDeleteAccountRequest = operations['i___delete-account']['requestBody']['content']['application/json']; export type IDeleteAccountRequest = operations['i___delete-account']['requestBody']['content']['application/json'];
export type IExportFollowingRequest = operations['i___export-following']['requestBody']['content']['application/json']; export type IExportFollowingRequest = operations['i___export-following']['requestBody']['content']['application/json'];
export type IFavoritesRequest = operations['i___favorites']['requestBody']['content']['application/json']; export type IFavoritesRequest = operations['i___favorites']['requestBody']['content']['application/json'];
@ -339,11 +363,13 @@ export type IGalleryLikesRequest = operations['i___gallery___likes']['requestBod
export type IGalleryLikesResponse = operations['i___gallery___likes']['responses']['200']['content']['application/json']; export type IGalleryLikesResponse = operations['i___gallery___likes']['responses']['200']['content']['application/json'];
export type IGalleryPostsRequest = operations['i___gallery___posts']['requestBody']['content']['application/json']; export type IGalleryPostsRequest = operations['i___gallery___posts']['requestBody']['content']['application/json'];
export type IGalleryPostsResponse = operations['i___gallery___posts']['responses']['200']['content']['application/json']; export type IGalleryPostsResponse = operations['i___gallery___posts']['responses']['200']['content']['application/json'];
export type IImportAntennasRequest = operations['i___import-antennas']['requestBody']['content']['application/json'];
export type IImportBlockingRequest = operations['i___import-blocking']['requestBody']['content']['application/json']; export type IImportBlockingRequest = operations['i___import-blocking']['requestBody']['content']['application/json'];
export type IImportFollowingRequest = operations['i___import-following']['requestBody']['content']['application/json']; export type IImportFollowingRequest = operations['i___import-following']['requestBody']['content']['application/json'];
export type IImportMutingRequest = operations['i___import-muting']['requestBody']['content']['application/json']; export type IImportMutingRequest = operations['i___import-muting']['requestBody']['content']['application/json'];
export type IImportUserListsRequest = operations['i___import-user-lists']['requestBody']['content']['application/json']; export type IImportUserListsRequest = operations['i___import-user-lists']['requestBody']['content']['application/json'];
export type IImportAntennasRequest = operations['i___import-antennas']['requestBody']['content']['application/json']; export type IMoveRequest = operations['i___move']['requestBody']['content']['application/json'];
export type IMoveResponse = operations['i___move']['responses']['200']['content']['application/json'];
export type INotificationsRequest = operations['i___notifications']['requestBody']['content']['application/json']; export type INotificationsRequest = operations['i___notifications']['requestBody']['content']['application/json'];
export type INotificationsResponse = operations['i___notifications']['responses']['200']['content']['application/json']; export type INotificationsResponse = operations['i___notifications']['responses']['200']['content']['application/json'];
export type INotificationsGroupedRequest = operations['i___notifications-grouped']['requestBody']['content']['application/json']; export type INotificationsGroupedRequest = operations['i___notifications-grouped']['requestBody']['content']['application/json'];
@ -356,16 +382,16 @@ export type IPinRequest = operations['i___pin']['requestBody']['content']['appli
export type IPinResponse = operations['i___pin']['responses']['200']['content']['application/json']; export type IPinResponse = operations['i___pin']['responses']['200']['content']['application/json'];
export type IReadAnnouncementRequest = operations['i___read-announcement']['requestBody']['content']['application/json']; export type IReadAnnouncementRequest = operations['i___read-announcement']['requestBody']['content']['application/json'];
export type IRegenerateTokenRequest = operations['i___regenerate-token']['requestBody']['content']['application/json']; export type IRegenerateTokenRequest = operations['i___regenerate-token']['requestBody']['content']['application/json'];
export type IRegistryGetRequest = operations['i___registry___get']['requestBody']['content']['application/json'];
export type IRegistryGetResponse = operations['i___registry___get']['responses']['200']['content']['application/json'];
export type IRegistryGetAllRequest = operations['i___registry___get-all']['requestBody']['content']['application/json']; export type IRegistryGetAllRequest = operations['i___registry___get-all']['requestBody']['content']['application/json'];
export type IRegistryGetAllResponse = operations['i___registry___get-all']['responses']['200']['content']['application/json']; export type IRegistryGetAllResponse = operations['i___registry___get-all']['responses']['200']['content']['application/json'];
export type IRegistryGetDetailRequest = operations['i___registry___get-detail']['requestBody']['content']['application/json']; export type IRegistryGetDetailRequest = operations['i___registry___get-detail']['requestBody']['content']['application/json'];
export type IRegistryGetDetailResponse = operations['i___registry___get-detail']['responses']['200']['content']['application/json']; export type IRegistryGetDetailResponse = operations['i___registry___get-detail']['responses']['200']['content']['application/json'];
export type IRegistryGetRequest = operations['i___registry___get']['requestBody']['content']['application/json'];
export type IRegistryGetResponse = operations['i___registry___get']['responses']['200']['content']['application/json'];
export type IRegistryKeysWithTypeRequest = operations['i___registry___keys-with-type']['requestBody']['content']['application/json'];
export type IRegistryKeysWithTypeResponse = operations['i___registry___keys-with-type']['responses']['200']['content']['application/json'];
export type IRegistryKeysRequest = operations['i___registry___keys']['requestBody']['content']['application/json']; export type IRegistryKeysRequest = operations['i___registry___keys']['requestBody']['content']['application/json'];
export type IRegistryKeysResponse = operations['i___registry___keys']['responses']['200']['content']['application/json']; export type IRegistryKeysResponse = operations['i___registry___keys']['responses']['200']['content']['application/json'];
export type IRegistryKeysWithTypeRequest = operations['i___registry___keys-with-type']['requestBody']['content']['application/json'];
export type IRegistryKeysWithTypeResponse = operations['i___registry___keys-with-type']['responses']['200']['content']['application/json'];
export type IRegistryRemoveRequest = operations['i___registry___remove']['requestBody']['content']['application/json']; export type IRegistryRemoveRequest = operations['i___registry___remove']['requestBody']['content']['application/json'];
export type IRegistryScopesWithDomainResponse = operations['i___registry___scopes-with-domain']['responses']['200']['content']['application/json']; export type IRegistryScopesWithDomainResponse = operations['i___registry___scopes-with-domain']['responses']['200']['content']['application/json'];
export type IRegistrySetRequest = operations['i___registry___set']['requestBody']['content']['application/json']; export type IRegistrySetRequest = operations['i___registry___set']['requestBody']['content']['application/json'];
@ -374,40 +400,31 @@ export type ISigninHistoryRequest = operations['i___signin-history']['requestBod
export type ISigninHistoryResponse = operations['i___signin-history']['responses']['200']['content']['application/json']; export type ISigninHistoryResponse = operations['i___signin-history']['responses']['200']['content']['application/json'];
export type IUnpinRequest = operations['i___unpin']['requestBody']['content']['application/json']; export type IUnpinRequest = operations['i___unpin']['requestBody']['content']['application/json'];
export type IUnpinResponse = operations['i___unpin']['responses']['200']['content']['application/json']; export type IUnpinResponse = operations['i___unpin']['responses']['200']['content']['application/json'];
export type IUpdateEmailRequest = operations['i___update-email']['requestBody']['content']['application/json'];
export type IUpdateEmailResponse = operations['i___update-email']['responses']['200']['content']['application/json'];
export type IUpdateRequest = operations['i___update']['requestBody']['content']['application/json']; export type IUpdateRequest = operations['i___update']['requestBody']['content']['application/json'];
export type IUpdateResponse = operations['i___update']['responses']['200']['content']['application/json']; export type IUpdateResponse = operations['i___update']['responses']['200']['content']['application/json'];
export type IMoveRequest = operations['i___move']['requestBody']['content']['application/json']; export type IUpdateEmailRequest = operations['i___update-email']['requestBody']['content']['application/json'];
export type IMoveResponse = operations['i___move']['responses']['200']['content']['application/json']; export type IUpdateEmailResponse = operations['i___update-email']['responses']['200']['content']['application/json'];
export type IWebhooksCreateRequest = operations['i___webhooks___create']['requestBody']['content']['application/json']; export type IWebhooksCreateRequest = operations['i___webhooks___create']['requestBody']['content']['application/json'];
export type IWebhooksCreateResponse = operations['i___webhooks___create']['responses']['200']['content']['application/json']; export type IWebhooksCreateResponse = operations['i___webhooks___create']['responses']['200']['content']['application/json'];
export type IWebhooksDeleteRequest = operations['i___webhooks___delete']['requestBody']['content']['application/json'];
export type IWebhooksListResponse = operations['i___webhooks___list']['responses']['200']['content']['application/json']; export type IWebhooksListResponse = operations['i___webhooks___list']['responses']['200']['content']['application/json'];
export type IWebhooksShowRequest = operations['i___webhooks___show']['requestBody']['content']['application/json']; export type IWebhooksShowRequest = operations['i___webhooks___show']['requestBody']['content']['application/json'];
export type IWebhooksShowResponse = operations['i___webhooks___show']['responses']['200']['content']['application/json']; export type IWebhooksShowResponse = operations['i___webhooks___show']['responses']['200']['content']['application/json'];
export type IWebhooksUpdateRequest = operations['i___webhooks___update']['requestBody']['content']['application/json'];
export type IWebhooksDeleteRequest = operations['i___webhooks___delete']['requestBody']['content']['application/json'];
export type IWebhooksTestRequest = operations['i___webhooks___test']['requestBody']['content']['application/json']; export type IWebhooksTestRequest = operations['i___webhooks___test']['requestBody']['content']['application/json'];
export type IWebhooksUpdateRequest = operations['i___webhooks___update']['requestBody']['content']['application/json'];
export type InviteCreateResponse = operations['invite___create']['responses']['200']['content']['application/json']; export type InviteCreateResponse = operations['invite___create']['responses']['200']['content']['application/json'];
export type InviteDeleteRequest = operations['invite___delete']['requestBody']['content']['application/json']; export type InviteDeleteRequest = operations['invite___delete']['requestBody']['content']['application/json'];
export type InviteLimitResponse = operations['invite___limit']['responses']['200']['content']['application/json'];
export type InviteListRequest = operations['invite___list']['requestBody']['content']['application/json']; export type InviteListRequest = operations['invite___list']['requestBody']['content']['application/json'];
export type InviteListResponse = operations['invite___list']['responses']['200']['content']['application/json']; export type InviteListResponse = operations['invite___list']['responses']['200']['content']['application/json'];
export type InviteLimitResponse = operations['invite___limit']['responses']['200']['content']['application/json'];
export type MetaRequest = operations['meta']['requestBody']['content']['application/json']; export type MetaRequest = operations['meta']['requestBody']['content']['application/json'];
export type MetaResponse = operations['meta']['responses']['200']['content']['application/json']; export type MetaResponse = operations['meta']['responses']['200']['content']['application/json'];
export type EmojisResponse = operations['emojis']['responses']['200']['content']['application/json'];
export type EmojiRequest = operations['emoji']['requestBody']['content']['application/json'];
export type EmojiResponse = operations['emoji']['responses']['200']['content']['application/json'];
export type MiauthGenTokenRequest = operations['miauth___gen-token']['requestBody']['content']['application/json']; export type MiauthGenTokenRequest = operations['miauth___gen-token']['requestBody']['content']['application/json'];
export type MiauthGenTokenResponse = operations['miauth___gen-token']['responses']['200']['content']['application/json']; export type MiauthGenTokenResponse = operations['miauth___gen-token']['responses']['200']['content']['application/json'];
export type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json']; export type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json'];
export type MuteDeleteRequest = operations['mute___delete']['requestBody']['content']['application/json']; export type MuteDeleteRequest = operations['mute___delete']['requestBody']['content']['application/json'];
export type MuteListRequest = operations['mute___list']['requestBody']['content']['application/json']; export type MuteListRequest = operations['mute___list']['requestBody']['content']['application/json'];
export type MuteListResponse = operations['mute___list']['responses']['200']['content']['application/json']; export type MuteListResponse = operations['mute___list']['responses']['200']['content']['application/json'];
export type RenoteMuteCreateRequest = operations['renote-mute___create']['requestBody']['content']['application/json'];
export type RenoteMuteDeleteRequest = operations['renote-mute___delete']['requestBody']['content']['application/json'];
export type RenoteMuteListRequest = operations['renote-mute___list']['requestBody']['content']['application/json'];
export type RenoteMuteListResponse = operations['renote-mute___list']['responses']['200']['content']['application/json'];
export type MyAppsRequest = operations['my___apps']['requestBody']['content']['application/json']; export type MyAppsRequest = operations['my___apps']['requestBody']['content']['application/json'];
export type MyAppsResponse = operations['my___apps']['responses']['200']['content']['application/json']; export type MyAppsResponse = operations['my___apps']['responses']['200']['content']['application/json'];
export type NotesRequest = operations['notes']['requestBody']['content']['application/json']; export type NotesRequest = operations['notes']['requestBody']['content']['application/json'];
@ -444,10 +461,10 @@ export type NotesRenotesRequest = operations['notes___renotes']['requestBody']['
export type NotesRenotesResponse = operations['notes___renotes']['responses']['200']['content']['application/json']; export type NotesRenotesResponse = operations['notes___renotes']['responses']['200']['content']['application/json'];
export type NotesRepliesRequest = operations['notes___replies']['requestBody']['content']['application/json']; export type NotesRepliesRequest = operations['notes___replies']['requestBody']['content']['application/json'];
export type NotesRepliesResponse = operations['notes___replies']['responses']['200']['content']['application/json']; export type NotesRepliesResponse = operations['notes___replies']['responses']['200']['content']['application/json'];
export type NotesSearchByTagRequest = operations['notes___search-by-tag']['requestBody']['content']['application/json'];
export type NotesSearchByTagResponse = operations['notes___search-by-tag']['responses']['200']['content']['application/json'];
export type NotesSearchRequest = operations['notes___search']['requestBody']['content']['application/json']; export type NotesSearchRequest = operations['notes___search']['requestBody']['content']['application/json'];
export type NotesSearchResponse = operations['notes___search']['responses']['200']['content']['application/json']; export type NotesSearchResponse = operations['notes___search']['responses']['200']['content']['application/json'];
export type NotesSearchByTagRequest = operations['notes___search-by-tag']['requestBody']['content']['application/json'];
export type NotesSearchByTagResponse = operations['notes___search-by-tag']['responses']['200']['content']['application/json'];
export type NotesShowRequest = operations['notes___show']['requestBody']['content']['application/json']; export type NotesShowRequest = operations['notes___show']['requestBody']['content']['application/json'];
export type NotesShowResponse = operations['notes___show']['responses']['200']['content']['application/json']; export type NotesShowResponse = operations['notes___show']['responses']['200']['content']['application/json'];
export type NotesStateRequest = operations['notes___state']['requestBody']['content']['application/json']; export type NotesStateRequest = operations['notes___state']['requestBody']['content']['application/json'];
@ -472,49 +489,57 @@ export type PagesShowRequest = operations['pages___show']['requestBody']['conten
export type PagesShowResponse = operations['pages___show']['responses']['200']['content']['application/json']; export type PagesShowResponse = operations['pages___show']['responses']['200']['content']['application/json'];
export type PagesUnlikeRequest = operations['pages___unlike']['requestBody']['content']['application/json']; export type PagesUnlikeRequest = operations['pages___unlike']['requestBody']['content']['application/json'];
export type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json']; export type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json'];
export type FlashCreateRequest = operations['flash___create']['requestBody']['content']['application/json'];
export type FlashCreateResponse = operations['flash___create']['responses']['200']['content']['application/json'];
export type FlashDeleteRequest = operations['flash___delete']['requestBody']['content']['application/json'];
export type FlashFeaturedRequest = operations['flash___featured']['requestBody']['content']['application/json'];
export type FlashFeaturedResponse = operations['flash___featured']['responses']['200']['content']['application/json'];
export type FlashLikeRequest = operations['flash___like']['requestBody']['content']['application/json'];
export type FlashShowRequest = operations['flash___show']['requestBody']['content']['application/json'];
export type FlashShowResponse = operations['flash___show']['responses']['200']['content']['application/json'];
export type FlashUnlikeRequest = operations['flash___unlike']['requestBody']['content']['application/json'];
export type FlashUpdateRequest = operations['flash___update']['requestBody']['content']['application/json'];
export type FlashMyRequest = operations['flash___my']['requestBody']['content']['application/json'];
export type FlashMyResponse = operations['flash___my']['responses']['200']['content']['application/json'];
export type FlashMyLikesRequest = operations['flash___my-likes']['requestBody']['content']['application/json'];
export type FlashMyLikesResponse = operations['flash___my-likes']['responses']['200']['content']['application/json'];
export type PingResponse = operations['ping']['responses']['200']['content']['application/json']; export type PingResponse = operations['ping']['responses']['200']['content']['application/json'];
export type PinnedUsersResponse = operations['pinned-users']['responses']['200']['content']['application/json']; export type PinnedUsersResponse = operations['pinned-users']['responses']['200']['content']['application/json'];
export type PromoReadRequest = operations['promo___read']['requestBody']['content']['application/json']; export type PromoReadRequest = operations['promo___read']['requestBody']['content']['application/json'];
export type RenoteMuteCreateRequest = operations['renote-mute___create']['requestBody']['content']['application/json'];
export type RenoteMuteDeleteRequest = operations['renote-mute___delete']['requestBody']['content']['application/json'];
export type RenoteMuteListRequest = operations['renote-mute___list']['requestBody']['content']['application/json'];
export type RenoteMuteListResponse = operations['renote-mute___list']['responses']['200']['content']['application/json'];
export type RequestResetPasswordRequest = operations['request-reset-password']['requestBody']['content']['application/json'];
export type ResetPasswordRequest = operations['reset-password']['requestBody']['content']['application/json'];
export type RetentionResponse = operations['retention']['responses']['200']['content']['application/json'];
export type ReversiCancelMatchRequest = operations['reversi___cancel-match']['requestBody']['content']['application/json'];
export type ReversiGamesRequest = operations['reversi___games']['requestBody']['content']['application/json'];
export type ReversiGamesResponse = operations['reversi___games']['responses']['200']['content']['application/json'];
export type ReversiInvitationsResponse = operations['reversi___invitations']['responses']['200']['content']['application/json'];
export type ReversiMatchRequest = operations['reversi___match']['requestBody']['content']['application/json'];
export type ReversiMatchResponse = operations['reversi___match']['responses']['200']['content']['application/json'];
export type ReversiShowGameRequest = operations['reversi___show-game']['requestBody']['content']['application/json'];
export type ReversiShowGameResponse = operations['reversi___show-game']['responses']['200']['content']['application/json'];
export type ReversiSurrenderRequest = operations['reversi___surrender']['requestBody']['content']['application/json'];
export type ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json'];
export type ReversiVerifyResponse = operations['reversi___verify']['responses']['200']['content']['application/json'];
export type RolesListResponse = operations['roles___list']['responses']['200']['content']['application/json']; export type RolesListResponse = operations['roles___list']['responses']['200']['content']['application/json'];
export type RolesNotesRequest = operations['roles___notes']['requestBody']['content']['application/json'];
export type RolesNotesResponse = operations['roles___notes']['responses']['200']['content']['application/json'];
export type RolesShowRequest = operations['roles___show']['requestBody']['content']['application/json']; export type RolesShowRequest = operations['roles___show']['requestBody']['content']['application/json'];
export type RolesShowResponse = operations['roles___show']['responses']['200']['content']['application/json']; export type RolesShowResponse = operations['roles___show']['responses']['200']['content']['application/json'];
export type RolesUsersRequest = operations['roles___users']['requestBody']['content']['application/json']; export type RolesUsersRequest = operations['roles___users']['requestBody']['content']['application/json'];
export type RolesUsersResponse = operations['roles___users']['responses']['200']['content']['application/json']; export type RolesUsersResponse = operations['roles___users']['responses']['200']['content']['application/json'];
export type RolesNotesRequest = operations['roles___notes']['requestBody']['content']['application/json'];
export type RolesNotesResponse = operations['roles___notes']['responses']['200']['content']['application/json'];
export type RequestResetPasswordRequest = operations['request-reset-password']['requestBody']['content']['application/json'];
export type ResetPasswordRequest = operations['reset-password']['requestBody']['content']['application/json'];
export type ServerInfoResponse = operations['server-info']['responses']['200']['content']['application/json']; export type ServerInfoResponse = operations['server-info']['responses']['200']['content']['application/json'];
export type StatsResponse = operations['stats']['responses']['200']['content']['application/json']; export type StatsResponse = operations['stats']['responses']['200']['content']['application/json'];
export type SwShowRegistrationRequest = operations['sw___show-registration']['requestBody']['content']['application/json'];
export type SwShowRegistrationResponse = operations['sw___show-registration']['responses']['200']['content']['application/json'];
export type SwUpdateRegistrationRequest = operations['sw___update-registration']['requestBody']['content']['application/json'];
export type SwUpdateRegistrationResponse = operations['sw___update-registration']['responses']['200']['content']['application/json'];
export type SwRegisterRequest = operations['sw___register']['requestBody']['content']['application/json']; export type SwRegisterRequest = operations['sw___register']['requestBody']['content']['application/json'];
export type SwRegisterResponse = operations['sw___register']['responses']['200']['content']['application/json']; export type SwRegisterResponse = operations['sw___register']['responses']['200']['content']['application/json'];
export type SwShowRegistrationRequest = operations['sw___show-registration']['requestBody']['content']['application/json'];
export type SwShowRegistrationResponse = operations['sw___show-registration']['responses']['200']['content']['application/json'];
export type SwUnregisterRequest = operations['sw___unregister']['requestBody']['content']['application/json']; export type SwUnregisterRequest = operations['sw___unregister']['requestBody']['content']['application/json'];
export type SwUpdateRegistrationRequest = operations['sw___update-registration']['requestBody']['content']['application/json'];
export type SwUpdateRegistrationResponse = operations['sw___update-registration']['responses']['200']['content']['application/json'];
export type TestRequest = operations['test']['requestBody']['content']['application/json']; export type TestRequest = operations['test']['requestBody']['content']['application/json'];
export type TestResponse = operations['test']['responses']['200']['content']['application/json']; export type TestResponse = operations['test']['responses']['200']['content']['application/json'];
export type UsernameAvailableRequest = operations['username___available']['requestBody']['content']['application/json']; export type UsernameAvailableRequest = operations['username___available']['requestBody']['content']['application/json'];
export type UsernameAvailableResponse = operations['username___available']['responses']['200']['content']['application/json']; export type UsernameAvailableResponse = operations['username___available']['responses']['200']['content']['application/json'];
export type UsersRequest = operations['users']['requestBody']['content']['application/json']; export type UsersRequest = operations['users']['requestBody']['content']['application/json'];
export type UsersResponse = operations['users']['responses']['200']['content']['application/json']; export type UsersResponse = operations['users']['responses']['200']['content']['application/json'];
export type UsersAchievementsRequest = operations['users___achievements']['requestBody']['content']['application/json'];
export type UsersAchievementsResponse = operations['users___achievements']['responses']['200']['content']['application/json'];
export type UsersClipsRequest = operations['users___clips']['requestBody']['content']['application/json']; export type UsersClipsRequest = operations['users___clips']['requestBody']['content']['application/json'];
export type UsersClipsResponse = operations['users___clips']['responses']['200']['content']['application/json']; export type UsersClipsResponse = operations['users___clips']['responses']['200']['content']['application/json'];
export type UsersFeaturedNotesRequest = operations['users___featured-notes']['requestBody']['content']['application/json'];
export type UsersFeaturedNotesResponse = operations['users___featured-notes']['responses']['200']['content']['application/json'];
export type UsersFlashsRequest = operations['users___flashs']['requestBody']['content']['application/json'];
export type UsersFlashsResponse = operations['users___flashs']['responses']['200']['content']['application/json'];
export type UsersFollowersRequest = operations['users___followers']['requestBody']['content']['application/json']; export type UsersFollowersRequest = operations['users___followers']['requestBody']['content']['application/json'];
export type UsersFollowersResponse = operations['users___followers']['responses']['200']['content']['application/json']; export type UsersFollowersResponse = operations['users___followers']['responses']['200']['content']['application/json'];
export type UsersFollowingRequest = operations['users___following']['requestBody']['content']['application/json']; export type UsersFollowingRequest = operations['users___following']['requestBody']['content']['application/json'];
@ -523,32 +548,28 @@ export type UsersGalleryPostsRequest = operations['users___gallery___posts']['re
export type UsersGalleryPostsResponse = operations['users___gallery___posts']['responses']['200']['content']['application/json']; export type UsersGalleryPostsResponse = operations['users___gallery___posts']['responses']['200']['content']['application/json'];
export type UsersGetFrequentlyRepliedUsersRequest = operations['users___get-frequently-replied-users']['requestBody']['content']['application/json']; export type UsersGetFrequentlyRepliedUsersRequest = operations['users___get-frequently-replied-users']['requestBody']['content']['application/json'];
export type UsersGetFrequentlyRepliedUsersResponse = operations['users___get-frequently-replied-users']['responses']['200']['content']['application/json']; export type UsersGetFrequentlyRepliedUsersResponse = operations['users___get-frequently-replied-users']['responses']['200']['content']['application/json'];
export type UsersFeaturedNotesRequest = operations['users___featured-notes']['requestBody']['content']['application/json'];
export type UsersFeaturedNotesResponse = operations['users___featured-notes']['responses']['200']['content']['application/json'];
export type UsersListsCreateRequest = operations['users___lists___create']['requestBody']['content']['application/json']; export type UsersListsCreateRequest = operations['users___lists___create']['requestBody']['content']['application/json'];
export type UsersListsCreateResponse = operations['users___lists___create']['responses']['200']['content']['application/json']; export type UsersListsCreateResponse = operations['users___lists___create']['responses']['200']['content']['application/json'];
export type UsersListsCreateFromPublicRequest = operations['users___lists___create-from-public']['requestBody']['content']['application/json'];
export type UsersListsCreateFromPublicResponse = operations['users___lists___create-from-public']['responses']['200']['content']['application/json'];
export type UsersListsDeleteRequest = operations['users___lists___delete']['requestBody']['content']['application/json']; export type UsersListsDeleteRequest = operations['users___lists___delete']['requestBody']['content']['application/json'];
export type UsersListsFavoriteRequest = operations['users___lists___favorite']['requestBody']['content']['application/json'];
export type UsersListsGetMembershipsRequest = operations['users___lists___get-memberships']['requestBody']['content']['application/json'];
export type UsersListsGetMembershipsResponse = operations['users___lists___get-memberships']['responses']['200']['content']['application/json'];
export type UsersListsListRequest = operations['users___lists___list']['requestBody']['content']['application/json']; export type UsersListsListRequest = operations['users___lists___list']['requestBody']['content']['application/json'];
export type UsersListsListResponse = operations['users___lists___list']['responses']['200']['content']['application/json']; export type UsersListsListResponse = operations['users___lists___list']['responses']['200']['content']['application/json'];
export type UsersListsPullRequest = operations['users___lists___pull']['requestBody']['content']['application/json']; export type UsersListsPullRequest = operations['users___lists___pull']['requestBody']['content']['application/json'];
export type UsersListsPushRequest = operations['users___lists___push']['requestBody']['content']['application/json']; export type UsersListsPushRequest = operations['users___lists___push']['requestBody']['content']['application/json'];
export type UsersListsShowRequest = operations['users___lists___show']['requestBody']['content']['application/json']; export type UsersListsShowRequest = operations['users___lists___show']['requestBody']['content']['application/json'];
export type UsersListsShowResponse = operations['users___lists___show']['responses']['200']['content']['application/json']; export type UsersListsShowResponse = operations['users___lists___show']['responses']['200']['content']['application/json'];
export type UsersListsFavoriteRequest = operations['users___lists___favorite']['requestBody']['content']['application/json'];
export type UsersListsUnfavoriteRequest = operations['users___lists___unfavorite']['requestBody']['content']['application/json']; export type UsersListsUnfavoriteRequest = operations['users___lists___unfavorite']['requestBody']['content']['application/json'];
export type UsersListsUpdateRequest = operations['users___lists___update']['requestBody']['content']['application/json']; export type UsersListsUpdateRequest = operations['users___lists___update']['requestBody']['content']['application/json'];
export type UsersListsUpdateResponse = operations['users___lists___update']['responses']['200']['content']['application/json']; export type UsersListsUpdateResponse = operations['users___lists___update']['responses']['200']['content']['application/json'];
export type UsersListsCreateFromPublicRequest = operations['users___lists___create-from-public']['requestBody']['content']['application/json'];
export type UsersListsCreateFromPublicResponse = operations['users___lists___create-from-public']['responses']['200']['content']['application/json'];
export type UsersListsUpdateMembershipRequest = operations['users___lists___update-membership']['requestBody']['content']['application/json']; export type UsersListsUpdateMembershipRequest = operations['users___lists___update-membership']['requestBody']['content']['application/json'];
export type UsersListsGetMembershipsRequest = operations['users___lists___get-memberships']['requestBody']['content']['application/json'];
export type UsersListsGetMembershipsResponse = operations['users___lists___get-memberships']['responses']['200']['content']['application/json'];
export type UsersNotesRequest = operations['users___notes']['requestBody']['content']['application/json']; export type UsersNotesRequest = operations['users___notes']['requestBody']['content']['application/json'];
export type UsersNotesResponse = operations['users___notes']['responses']['200']['content']['application/json']; export type UsersNotesResponse = operations['users___notes']['responses']['200']['content']['application/json'];
export type UsersPagesRequest = operations['users___pages']['requestBody']['content']['application/json']; export type UsersPagesRequest = operations['users___pages']['requestBody']['content']['application/json'];
export type UsersPagesResponse = operations['users___pages']['responses']['200']['content']['application/json']; export type UsersPagesResponse = operations['users___pages']['responses']['200']['content']['application/json'];
export type UsersFlashsRequest = operations['users___flashs']['requestBody']['content']['application/json'];
export type UsersFlashsResponse = operations['users___flashs']['responses']['200']['content']['application/json'];
export type UsersReactionsRequest = operations['users___reactions']['requestBody']['content']['application/json']; export type UsersReactionsRequest = operations['users___reactions']['requestBody']['content']['application/json'];
export type UsersReactionsResponse = operations['users___reactions']['responses']['200']['content']['application/json']; export type UsersReactionsResponse = operations['users___reactions']['responses']['200']['content']['application/json'];
export type UsersRecommendationRequest = operations['users___recommendation']['requestBody']['content']['application/json']; export type UsersRecommendationRequest = operations['users___recommendation']['requestBody']['content']['application/json'];
@ -556,31 +577,12 @@ export type UsersRecommendationResponse = operations['users___recommendation']['
export type UsersRelationRequest = operations['users___relation']['requestBody']['content']['application/json']; export type UsersRelationRequest = operations['users___relation']['requestBody']['content']['application/json'];
export type UsersRelationResponse = operations['users___relation']['responses']['200']['content']['application/json']; export type UsersRelationResponse = operations['users___relation']['responses']['200']['content']['application/json'];
export type UsersReportAbuseRequest = operations['users___report-abuse']['requestBody']['content']['application/json']; export type UsersReportAbuseRequest = operations['users___report-abuse']['requestBody']['content']['application/json'];
export type UsersSearchByUsernameAndHostRequest = operations['users___search-by-username-and-host']['requestBody']['content']['application/json'];
export type UsersSearchByUsernameAndHostResponse = operations['users___search-by-username-and-host']['responses']['200']['content']['application/json'];
export type UsersSearchRequest = operations['users___search']['requestBody']['content']['application/json']; export type UsersSearchRequest = operations['users___search']['requestBody']['content']['application/json'];
export type UsersSearchResponse = operations['users___search']['responses']['200']['content']['application/json']; export type UsersSearchResponse = operations['users___search']['responses']['200']['content']['application/json'];
export type UsersSearchByUsernameAndHostRequest = operations['users___search-by-username-and-host']['requestBody']['content']['application/json'];
export type UsersSearchByUsernameAndHostResponse = operations['users___search-by-username-and-host']['responses']['200']['content']['application/json'];
export type UsersShowRequest = operations['users___show']['requestBody']['content']['application/json']; export type UsersShowRequest = operations['users___show']['requestBody']['content']['application/json'];
export type UsersShowResponse = operations['users___show']['responses']['200']['content']['application/json']; export type UsersShowResponse = operations['users___show']['responses']['200']['content']['application/json'];
export type UsersAchievementsRequest = operations['users___achievements']['requestBody']['content']['application/json'];
export type UsersAchievementsResponse = operations['users___achievements']['responses']['200']['content']['application/json'];
export type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json']; export type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json'];
export type FetchRssRequest = operations['fetch-rss']['requestBody']['content']['application/json']; export type V2AdminEmojiListRequest = operations['v2___admin___emoji___list']['requestBody']['content']['application/json'];
export type FetchRssResponse = operations['fetch-rss']['responses']['200']['content']['application/json']; export type V2AdminEmojiListResponse = operations['v2___admin___emoji___list']['responses']['200']['content']['application/json'];
export type FetchExternalResourcesRequest = operations['fetch-external-resources']['requestBody']['content']['application/json'];
export type FetchExternalResourcesResponse = operations['fetch-external-resources']['responses']['200']['content']['application/json'];
export type RetentionResponse = operations['retention']['responses']['200']['content']['application/json'];
export type BubbleGameRegisterRequest = operations['bubble-game___register']['requestBody']['content']['application/json'];
export type BubbleGameRankingRequest = operations['bubble-game___ranking']['requestBody']['content']['application/json'];
export type BubbleGameRankingResponse = operations['bubble-game___ranking']['responses']['200']['content']['application/json'];
export type ReversiCancelMatchRequest = operations['reversi___cancel-match']['requestBody']['content']['application/json'];
export type ReversiGamesRequest = operations['reversi___games']['requestBody']['content']['application/json'];
export type ReversiGamesResponse = operations['reversi___games']['responses']['200']['content']['application/json'];
export type ReversiMatchRequest = operations['reversi___match']['requestBody']['content']['application/json'];
export type ReversiMatchResponse = operations['reversi___match']['responses']['200']['content']['application/json'];
export type ReversiInvitationsResponse = operations['reversi___invitations']['responses']['200']['content']['application/json'];
export type ReversiShowGameRequest = operations['reversi___show-game']['requestBody']['content']['application/json'];
export type ReversiShowGameResponse = operations['reversi___show-game']['responses']['200']['content']['application/json'];
export type ReversiSurrenderRequest = operations['reversi___surrender']['requestBody']['content']['application/json'];
export type ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json'];
export type ReversiVerifyResponse = operations['reversi___verify']['responses']['200']['content']['application/json'];

View File

@ -33,6 +33,7 @@ export type FederationInstance = components['schemas']['FederationInstance'];
export type GalleryPost = components['schemas']['GalleryPost']; export type GalleryPost = components['schemas']['GalleryPost'];
export type EmojiSimple = components['schemas']['EmojiSimple']; export type EmojiSimple = components['schemas']['EmojiSimple'];
export type EmojiDetailed = components['schemas']['EmojiDetailed']; export type EmojiDetailed = components['schemas']['EmojiDetailed'];
export type EmojiDetailedAdmin = components['schemas']['EmojiDetailedAdmin'];
export type Flash = components['schemas']['Flash']; export type Flash = components['schemas']['Flash'];
export type Signin = components['schemas']['Signin']; export type Signin = components['schemas']['Signin'];
export type RoleCondFormulaLogics = components['schemas']['RoleCondFormulaLogics']; export type RoleCondFormulaLogics = components['schemas']['RoleCondFormulaLogics'];

File diff suppressed because it is too large Load Diff