Introduce OpenAPI specs (#4351)

* wip

* wip

* wip

* Update index.ts

* Update gen-openapi-spec.ts

* Update api.ja-JP.md

* Fix

* Improve doc

* Update gen-openapi-spec.ts

* Update redoc.html

* Improve doc

* Update gen-openapi-spec.ts

* Improve doc

* Update CHANGELOG.md
This commit is contained in:
syuilo 2019-02-23 11:20:58 +09:00 committed by GitHub
parent 68a6758302
commit 52774bbe64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
173 changed files with 1091 additions and 876 deletions

View file

@ -3,6 +3,7 @@ ChangeLog
unreleasded
----------
* APIドキュメント刷新
* /api/v1/instance/peers 復活
* 「返信が遷移後も残り続ける問題を修正」([9beddc9](https://github.com/syuilo/misskey/commit/9beddc941a716f1322ae0b7d71d159edd642a399)) によって遷移前に返信が表示されなくなった問題を修正
* デッキモードにてユーザーのプロフィールを連続で見たとき、アクティビティや画像が前のユーザーのもののまま表示される問題を修正

BIN
assets/api-doc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -102,7 +102,7 @@
"bcryptjs": "2.4.3",
"bee-queue": "1.2.2",
"bootstrap-vue": "2.0.0-rc.11",
"cafy": "14.0.1",
"cafy": "15.1.0",
"chai": "4.2.0",
"chai-http": "4.2.1",
"chalk": "2.4.2",

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Misskey API</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
ReDoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-url='/api.json'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body>
</html>

View file

@ -74,7 +74,7 @@ APIはすべてリクエストのパラメータ・レスポンスともにJSON
ストリーミングAPIも提供しています。
APIリファレンスもご確認ください。
[APIリファレンス](/api-doc)もご確認ください。
### レートリミット
Misskey APIにはレートリミットがあり、短時間のうちに多数のリクエストを送信すると、一定時間APIを利用することができなくなることがあります。

View file

@ -1,40 +0,0 @@
@import "../style"
#url
padding 8px 12px 8px 8px
font-family Consolas, 'Courier New', Courier, Monaco, monospace
color #fff
background #222e40
border-radius 4px
overflow auto
white-space nowrap
> .method
display inline-block
margin 0 8px 0 0
padding 0 6px
color #fff
background #17afc7
border-radius 4px
user-select none
pointer-events none
> .host
opacity 0.7
#stability
padding 8px 12px
color #fff
border-radius 4px
&.deprecated
background #f42443
&.experimental
background #f2781a
&.stable
background #3dcc90
> b
margin-left 4px

View file

@ -1,81 +0,0 @@
extends ../../base
include ../mixins
block meta
link(rel="stylesheet" href="/docs/assets/api/endpoints/style.css")
block main
h1= title
p#url
span.method POST
span.host
= endpointUrl.host
| /
span.path= endpointUrl.path
- var stability = endpoint.stability || 'experimental';
p#stability(class=stability)
| Stability:
b= stability
if endpoint.desc
p#desc= endpoint.desc[lang] || endpoint.desc['ja-JP']
if endpoint.requireCredential
div.ui.info: p
i.fas.fa-id-card-alt(style="margin-right: 4px")
= i18n('docs.api.endpoints.require-credential')
if endpoint.kind
div.ui.info: p
i.fas.fa-unlock-alt(style="margin-right: 4px")
!= i18n('docs.api.endpoints.require-permission').replace('{permission}', `<code>${endpoint.kind}</code>`)
if endpoint.limit
div.ui.info.warn: p
i.far.fa-clock(style="margin-right: 4px")
b!= i18n('docs.api.endpoints.has-limit')
if endpoint.limit.duration
!= i18n('docs.api.endpoints.duration-limit').replace('{duration}', endpoint.limit.duration).replace('{max}', endpoint.limit.max)
if endpoint.limit.minInterval
!= i18n('docs.api.endpoints.min-interval-limit').replace('{interval}', endpoint.limit.minInterval)
if params && Object.keys(params).length > 0
section
h2= i18n('docs.api.endpoints.params')
+propTable(params)
if paramDefs
each paramDef in paramDefs
section(id= paramDef.name)
h3= paramDef.name
+propTable(paramDef.params)
if params && Object.keys(params).length == 0
section
h2= i18n('docs.api.endpoints.params')
p= i18n('docs.api.endpoints.no-params')
if res
section
h2= i18n('docs.api.endpoints.res')
if resProps
+propTable(resProps)
if resDefs
each resDef in resDefs
section(id= resDef.name)
h3= resDef.name
+propTable(resDef.props)
else
if res.type.startsWith('entity')
a(href=`/docs/${lang}/api/entities/${kebab(res.entity)}`)= res.entity
block footer
div.ui.info: p
i.fas.fa-info-circle(style="margin-right: 4px")
= i18n('docs.api.endpoints.generated')
p
= i18n('docs.api.endpoints.show-src')
a(href=src target="_blank")= i18n('docs.api.endpoints.show-src-link')

View file

@ -1,90 +0,0 @@
name: "DriveFile"
desc:
ja-JP: "ドライブのファイル。"
en-US: "A file of Drive."
props:
id:
type: "id"
optional: false
desc:
ja-JP: "ファイルID"
en-US: "The ID of this file"
createdAt:
type: "date"
optional: false
desc:
ja-JP: "アップロード日時"
en-US: "The upload date of this file"
userId:
type: "id(User)"
optional: false
desc:
ja-JP: "所有者ID"
en-US: "The ID of the owner of this file"
user:
type: "entity(User)"
optional: true
desc:
ja-JP: "所有者"
en-US: "The owner of this file"
name:
type: "string"
optional: false
desc:
ja-JP: "ファイル名"
en-US: "The name of this file"
md5:
type: "string"
optional: false
desc:
ja-JP: "ファイルのMD5ハッシュ値"
en-US: "The md5 hash value of this file"
type:
type: "string"
optional: false
desc:
ja-JP: "ファイルの種類"
en-US: "The type of this file"
datasize:
type: "number"
optional: false
desc:
ja-JP: "ファイルサイズ(bytes)"
en-US: "The size of this file (bytes)"
url:
type: "string"
optional: false
desc:
ja-JP: "ファイルのURL"
en-US: "The URL of this file"
folderId:
type: "id(DriveFolder)"
optional: true
desc:
ja-JP: "フォルダID"
en-US: "The ID of the folder of this file"
folder:
type: "entity(DriveFolder)"
optional: true
desc:
ja-JP: "フォルダ"
en-US: "The folder of this file"
isSensitive:
type: "boolean"
optional: true
desc:
ja-JP: "このメディアが「閲覧注意」(NSFW)かどうか"
en-US: "Whether this media is NSFW"

View file

@ -1,41 +0,0 @@
name: "DriveFolder"
desc:
ja-JP: "ドライブのフォルダを表します。"
en-US: "A folder of Drive."
props:
id:
type: "id"
optional: false
desc:
ja-JP: "フォルダID"
en-US: "The ID of this folder"
createdAt:
type: "date"
optional: false
desc:
ja-JP: "作成日時"
en-US: "The created date of this folder"
userId:
type: "id(User)"
optional: false
desc:
ja-JP: "所有者ID"
en-US: "The ID of the owner of this folder"
parentId:
type: "entity(DriveFolder)"
optional: false
desc:
ja-JP: "親フォルダのID (ルートなら null)"
en-US: "The ID of parent folder"
name:
type: "string"
optional: false
desc:
ja-JP: "フォルダ名"
en-US: "The name of this folder"

View file

@ -1,211 +0,0 @@
name: "Note"
desc:
ja-JP: "投稿。"
en-US: "A note."
props:
id:
type: "id"
optional: false
desc:
ja-JP: "投稿ID"
en-US: "The ID of this note"
createdAt:
type: "date"
optional: false
desc:
ja-JP: "投稿日時"
en-US: "The posted date of this note"
viaMobile:
type: "boolean"
optional: true
desc:
ja-JP: "モバイル端末から投稿したか否か(自己申告であることに留意)"
en-US: "Whether this note sent via a mobile device"
localOnly:
type: "boolean"
optional: true
desc:
ja-JP: "ローカルのみに公開する投稿か否か"
en-US: "Whether this note is no federation"
text:
type: "string"
optional: true
desc:
ja-JP: "投稿の本文"
en-US: "The text of this note"
fileIds:
type: "id(DriveFile)[]"
optional: true
desc:
ja-JP: "添付されているファイルのID (なければレスポンスでは空配列)"
en-US: "The IDs of the attached files (empty array for response if no files is attached)"
files:
type: "entity(DriveFile)[]"
optional: true
desc:
ja-JP: "添付されているファイル"
en-US: "The attached files"
userId:
type: "id(User)"
optional: false
desc:
ja-JP: "投稿者ID"
en-US: "The ID of author of this note"
user:
type: "entity(User)"
optional: true
desc:
ja-JP: "投稿者"
en-US: "The author of this note"
myReaction:
type: "string"
optional: true
desc:
ja-JP: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>"
en-US: "The your <a href='/docs/api/reactions'>reaction</a> of this note"
renoteCount:
type: "number"
optional: false
desc:
ja-JP: "この投稿がRenoteされた数"
en-US: "The number of renotes for this post"
repliesCount:
type: "number"
optional: false
desc:
ja-JP: "この投稿に返信された数"
en-US: "The number of replies to this post"
reactionCounts:
type: "object"
optional: false
desc:
ja-JP: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト"
replyId:
type: "id(Note)"
optional: true
desc:
ja-JP: "返信した投稿のID"
en-US: "The ID of the replyed note"
reply:
type: "entity(Note)"
optional: true
desc:
ja-JP: "返信した投稿"
en-US: "The replyed note"
renoteId:
type: "id(Note)"
optional: true
desc:
ja-JP: "引用した投稿のID"
en-US: "The ID of the quoted note"
renote:
type: "entity(Note)"
optional: true
desc:
ja-JP: "引用した投稿"
en-US: "The quoted note"
poll:
type: "object"
optional: true
desc:
ja-JP: "投票"
en-US: "The poll"
props:
choices:
type: "object[]"
optional: false
desc:
ja-JP: "投票の選択肢"
en-US: "The choices of this poll"
props:
id:
type: "number"
optional: false
desc:
ja-JP: "選択肢ID"
en-US: "The ID of this choice"
isVoted:
type: "boolean"
optional: true
desc:
ja-JP: "自分がこの選択肢に投票したかどうか"
en-US: "Whether you voted to this choice"
text:
type: "string"
optional: false
desc:
ja-JP: "選択肢本文"
en-US: "The text of this choice"
votes:
type: "number"
optional: false
desc:
ja-JP: "この選択肢に投票された数"
en-US: "The number voted for this choice"
geo:
type: "object"
optional: true
desc:
ja-JP: "位置情報"
en-US: "Geo location"
props:
coordinates:
type: "number[]"
optional: false
desc:
ja-JP: "座標。最初に経度:-180〜180で表す。最後に緯度-90〜90で表す。"
altitude:
type: "number"
optional: false
desc:
ja-JP: "高度。メートル単位で表す。"
accuracy:
type: "number"
optional: false
desc:
ja-JP: "緯度、経度の精度。メートル単位で表す。"
altitudeAccuracy:
type: "number"
optional: false
desc:
ja-JP: "高度の精度。メートル単位で表す。"
heading:
type: "number"
optional: false
desc:
ja-JP: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。"
speed:
type: "number"
optional: false
desc:
ja-JP: "速度。メートル / 秒数で表す。"

View file

@ -1 +0,0 @@
@import "../style"

View file

@ -1,174 +0,0 @@
name: "User"
desc:
ja-JP: "ユーザー。"
en-US: "A user."
props:
id:
type: "id"
optional: false
desc:
ja-JP: "ユーザーID"
en-US: "The ID of this user"
createdAt:
type: "date"
optional: false
desc:
ja-JP: "アカウント作成日時"
en-US: "The registered date of this user"
username:
type: "string"
optional: false
desc:
ja-JP: "ユーザー名"
en-US: "The username of this user"
description:
type: "string"
optional: false
desc:
ja-JP: "アカウントの説明(自己紹介)"
en-US: "The description of this user"
avatarId:
type: "id(DriveFile)"
optional: true
desc:
ja-JP: "アバターのID"
en-US: "The ID of the avatar of this user"
avatarUrl:
type: "string"
optional: false
desc:
ja-JP: "アバターのURL"
en-US: "The URL of the avatar of this user"
bannerId:
type: "id(DriveFile)"
optional: true
desc:
ja-JP: "バナーのID"
en-US: "The ID of the banner of this user"
bannerUrl:
type: "string"
optional: false
desc:
ja-JP: "バナーのURL"
en-US: "The URL of the banner of this user"
followersCount:
type: "number"
optional: false
desc:
ja-JP: "フォロワーの数"
en-US: "The number of the followers for this user"
followingCount:
type: "number"
optional: false
desc:
ja-JP: "フォローしているユーザーの数"
en-US: "The number of the following users for this user"
isFollowing:
type: "boolean"
optional: true
desc:
ja-JP: "自分がこのユーザーをフォローしているか"
isFollowed:
type: "boolean"
optional: true
desc:
ja-JP: "自分がこのユーザーにフォローされているか"
isMuted:
type: "boolean"
optional: true
desc:
ja-JP: "自分がこのユーザーをミュートしているか"
en-US: "Whether you muted this user"
notesCount:
type: "number"
optional: false
desc:
ja-JP: "投稿の数"
en-US: "The number of the notes of this user"
pinnedNotes:
type: "entity(Note)[]"
optional: true
desc:
ja-JP: "ピン留めされた投稿"
en-US: "The pinned note of this user"
pinnedNoteIds:
type: "id(Note)[]"
optional: true
desc:
ja-JP: "ピン留めされた投稿のID"
en-US: "The ID of the pinned note of this user"
host:
type: "string | null"
optional: false
desc:
ja-JP: "ホスト (例: example.com:3000)"
en-US: "Host (e.g. example.com:3000)"
twitter:
type: "object"
optional: true
desc:
ja-JP: "連携されているTwitterアカウント情報"
en-US: "The info of the connected twitter account of this user"
props:
userId:
type: "string"
optional: false
desc:
ja-JP: "ユーザーID"
en-US: "The user ID"
screenName:
type: "string"
optional: false
desc:
ja-JP: "ユーザー名"
en-US: "The screen name of this user"
isBot:
type: "boolean"
optional: true
desc:
ja-JP: "botか否か(自己申告であることに留意)"
en-US: "Whether is bot or not"
profile:
type: "object"
optional: false
desc:
ja-JP: "プロフィール"
en-US: "The profile of this user"
props:
location:
type: "string"
optional: true
desc:
ja-JP: "場所"
en-US: "The location of this user"
birthday:
type: "string"
optional: true
desc:
ja-JP: "誕生日 (YYYY-MM-DD)"
en-US: "The birthday of this user (YYYY-MM-DD)"

View file

@ -1,20 +0,0 @@
extends ../../base
include ../mixins
block meta
link(rel="stylesheet" href="/docs/assets/api/entities/style.css")
block main
h1= name
p#desc= desc[lang] || desc['ja-JP']
section
h2= i18n('docs.api.entities.properties')
+propTable(props)
if propDefs
each propDef in propDefs
section(id= propDef.name)
h3= propDef.name
+propTable(propDef.props)

View file

@ -1,34 +0,0 @@
mixin type(prop)
i= prop.type
if prop.kind == 'id'
if prop.entity
| (
a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
| ID)
else
| (ID)
else if prop.kind == 'entity'
| (
a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity
| )
else if prop.kind == 'object'
if prop.hasDef
| (
a(href=`#${prop.name}`)= prop.name
| )
else if prop.kind == 'date'
| (Date)
mixin propTable(props)
table.props
thead: tr
th= i18n('docs.api.props.name')
th= i18n('docs.api.props.type')
th= i18n('docs.api.props.description')
tbody
each prop in props
tr
td.name= prop.name
td.type
+type(prop)
td.desc!= prop.desc ? prop.desc[lang] || prop.desc['ja-JP'] : null

View file

@ -1,11 +0,0 @@
@import "../style"
table.props
.name
font-weight bold
.name
.type
.optional
font-family Consolas, 'Courier New', Courier, Monaco, monospace

View file

@ -17,17 +17,6 @@ html(lang= lang)
ul
each doc in docs
li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja-JP']
section
h2 API
ul
li Entities
ul
each entity in entities
li: a(href=`/docs/${lang}/api/entities/${kebab(entity)}`)= entity
li Endpoints
ul
each endpoint in endpoints
li: a(href=`/docs/${lang}/api/endpoints/${kebab(endpoint.name)}`)= endpoint.name
main
article
block main

View file

@ -26,6 +26,8 @@ export type ObjectId = mongo.ObjectID;
* ID
*/
export default class ID<Maybe = string> extends Context<string | Maybe> {
public readonly name = 'ID';
constructor(optional = false, nullable = false) {
super(optional, nullable);
@ -38,7 +40,7 @@ export default class ID<Maybe = string> extends Context<string | Maybe> {
}
public getType() {
return super.getType('string');
return super.getType('String');
}
public makeOptional(): ID<undefined> {

View file

@ -26,7 +26,7 @@ export default (endpoint: IEndpoint, ctx: Koa.BaseContext) => new Promise((res)
call(endpoint.name, user, app, body, (ctx.req as any).file).then(res => {
reply(res);
}).catch(e => {
reply(e.kind == 'client' ? 400 : 500, e);
reply(e.httpStatusCode ? e.httpStatusCode : e.kind == 'client' ? 400 : 500, e);
});
}).catch(() => {
reply(403, new ApiError({

View file

@ -21,6 +21,7 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
message: 'No such endpoint.',
code: 'NO_SUCH_ENDPOINT',
id: 'f8080b67-5f9c-4eb7-8c18-7f1eeae8f709',
httpStatusCode: 404
});
}
@ -33,6 +34,7 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
message: 'Credential required.',
code: 'CREDENTIAL_REQUIRED',
id: '1384574d-a912-4b81-8601-c7b1c4085df1',
httpStatusCode: 401
});
}
@ -63,6 +65,7 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
message: 'Rate limit exceeded. Please try again later.',
code: 'RATE_LIMIT_EXCEEDED',
id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef',
httpStatusCode: 429
});
});
}

View file

@ -2,18 +2,30 @@ import { Context } from 'cafy';
import * as path from 'path';
import * as glob from 'glob';
export type Param = {
validator: Context<any>;
transform?: any;
default?: any;
desc?: { [key: string]: string };
ref?: string;
};
export interface IEndpointMeta {
stability?: string; //'deprecated' | 'experimental' | 'stable';
desc?: { [key: string]: string };
tags?: string[];
params?: {
[key: string]: Param;
};
errors?: {
[key: string]: {
validator: Context<any>;
transform?: any;
default?: any;
desc?: { [key: string]: string };
ref?: string;
message: string;
code: string;
id: string;
};
};

View file

@ -4,6 +4,8 @@ import Report, { packMany } from '../../../../models/abuse-user-report';
import define from '../../define';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -4,6 +4,8 @@ import define from '../../../define';
import { fallback } from '../../../../../prelude/symbol';
export const meta = {
tags: ['admin'],
requireCredential: false,
requireModerator: true,

View file

@ -5,6 +5,8 @@ import DriveFile from '../../../../../models/drive-file';
import { ApiError } from '../../../error';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -7,6 +7,8 @@ export const meta = {
'ja-JP': 'カスタム絵文字を追加します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -7,6 +7,8 @@ export const meta = {
'ja-JP': 'カスタム絵文字を取得します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -8,6 +8,8 @@ export const meta = {
'ja-JP': 'カスタム絵文字を削除します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -8,6 +8,8 @@ export const meta = {
'ja-JP': 'カスタム絵文字を更新します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -5,6 +5,8 @@ import User from '../../../../../models/user';
import deleteFollowing from '../../../../../services/following/delete';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -3,6 +3,8 @@ import define from '../../../define';
import Instance from '../../../../../models/instance';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -7,6 +7,8 @@ export const meta = {
'ja-JP': '招待コードを発行します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Mark a user as moderator.'
},
tags: ['admin'],
requireCredential: true,
requireAdmin: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Unmark a user as moderator.'
},
tags: ['admin'],
requireCredential: true,
requireAdmin: true,

View file

@ -2,6 +2,8 @@ import define from '../../../define';
import { destroy } from '../../../../../queue';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -4,6 +4,8 @@ import define from '../../define';
import AbuseUserReport from '../../../../models/abuse-user-report';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': '指定したユーザーのパスワードをリセットします。',
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -8,6 +8,8 @@ export const meta = {
'ja-JP': '指定したユーザーの情報を取得します。',
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -4,6 +4,8 @@ import define from '../../define';
import { fallback } from '../../../../prelude/symbol';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Make silence a user.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Suspend a user.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Unsilence a user.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Unsuspend a user.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Mark a user as unverified.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -7,6 +7,8 @@ export const meta = {
'ja-JP': 'インスタンスの設定を更新します。'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -11,6 +11,8 @@ export const meta = {
'en-US': 'Update specified remote user information.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Mark a user as verified.'
},
tags: ['admin'],
requireCredential: true,
requireModerator: true,

View file

@ -3,6 +3,8 @@ import define from '../../define';
import fetchMeta from '../../../../misc/fetch-meta';
export const meta = {
tags: ['hashtags'],
requireCredential: false,
};

View file

@ -10,6 +10,8 @@ import Resolver from '../../../../remote/activitypub/resolver';
import { ApiError } from '../../error';
export const meta = {
tags: ['federation'],
desc: {
'ja-JP': 'URIを指定してActivityPubオブジェクトを参照します。'
},

View file

@ -4,6 +4,8 @@ import App, { pack } from '../../../../models/app';
import define from '../../define';
export const meta = {
tags: ['app'],
requireCredential: false,
params: {

View file

@ -5,6 +5,8 @@ import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
tags: ['app'],
params: {
appId: {
validator: $.type(ID),

View file

@ -8,6 +8,8 @@ import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
tags: ['auth'],
requireCredential: true,
secure: true,

View file

@ -7,6 +7,8 @@ import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
tags: ['auth'],
requireCredential: false,
params: {

View file

@ -4,6 +4,8 @@ import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
tags: ['auth'],
requireCredential: false,
params: {

View file

@ -7,6 +7,8 @@ import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
tags: ['auth'],
requireCredential: false,
params: {

View file

@ -16,6 +16,8 @@ export const meta = {
'en-US': 'Block a user.'
},
tags: ['blocking', 'users'],
limit: {
duration: ms('1hour'),
max: 100

View file

@ -16,6 +16,8 @@ export const meta = {
'en-US': 'Unblock a user.'
},
tags: ['blocking', 'users'],
limit: {
duration: ms('1hour'),
max: 100

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Get blocking users.'
},
tags: ['blocking', 'account'],
requireCredential: true,
kind: 'following-read',

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'アクティブユーザーのチャートを取得します。'
},
tags: ['charts', 'users'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'ドライブのチャートを取得します。'
},
tags: ['charts', 'drive'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'フェデレーションのチャートを取得します。'
},
tags: ['charts'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'ハッシュタグごとのチャートを取得します。'
},
tags: ['charts', 'hashtags'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -31,7 +33,14 @@ export const meta = {
'ja-JP': '対象のハッシュタグ'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'インスタンスごとのチャートを取得します。'
},
tags: ['charts'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -32,7 +34,14 @@ export const meta = {
'en-US': 'Target instance host'
}
}
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'ネットワークのチャートを取得します。'
},
tags: ['charts'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': '投稿のチャートを取得します。'
},
tags: ['charts', 'notes'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': 'ユーザーごとのドライブのチャートを取得します。'
},
tags: ['charts', 'drive', 'users'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -34,7 +36,14 @@ export const meta = {
'en-US': 'Target user ID'
}
}
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': 'ユーザーごとのフォロー/フォロワーのチャートを取得します。'
},
tags: ['charts', 'users', 'following'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -34,7 +36,14 @@ export const meta = {
'en-US': 'Target user ID'
}
}
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': 'ユーザーごとの投稿のチャートを取得します。'
},
tags: ['charts', 'users', 'notes'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -34,7 +36,14 @@ export const meta = {
'en-US': 'Target user ID'
}
}
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': 'ユーザーごとの被リアクション数のチャートを取得します。'
},
tags: ['charts', 'users', 'reactions'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -34,7 +36,14 @@ export const meta = {
'en-US': 'Target user ID'
}
}
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -9,6 +9,8 @@ export const meta = {
'ja-JP': 'ユーザーのチャートを取得します。'
},
tags: ['charts', 'users'],
params: {
span: {
validator: $.str.or(['day', 'hour']),
@ -24,7 +26,14 @@ export const meta = {
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
}
},
}
},
res: {
type: 'array',
items: {
type: 'object',
},
},
};
export default define(meta, async (ps) => {

View file

@ -8,6 +8,8 @@ export const meta = {
'en-US': 'Get drive information.'
},
tags: ['drive', 'account'],
requireCredential: true,
kind: 'drive-read'

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Get files of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',
@ -38,7 +40,14 @@ export const meta = {
type: {
validator: $.optional.str.match(/^[a-zA-Z\/\-\*]+$/)
}
}
},
res: {
type: 'array',
items: {
type: 'DriveFile',
},
},
};
export default define(meta, async (ps, user) => {

View file

@ -13,6 +13,8 @@ export const meta = {
'en-US': 'Get the notes that specified file of drive attached.'
},
tags: ['drive', 'notes'],
requireCredential: true,
kind: 'drive-read',

View file

@ -8,6 +8,8 @@ export const meta = {
'en-US': 'Returns whether the file with the given MD5 hash exists in the user\'s drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',

View file

@ -13,6 +13,8 @@ export const meta = {
'en-US': 'Upload a file to drive.'
},
tags: ['drive'],
requireCredential: true,
limit: {
@ -35,7 +37,7 @@ export const meta = {
},
isSensitive: {
validator: $.optional.or($.bool, $.str),
validator: $.optional.either($.bool, $.str),
default: false,
transform: (v: any): boolean => v === true || v === 'true',
desc: {
@ -45,7 +47,7 @@ export const meta = {
},
force: {
validator: $.optional.or($.bool, $.str),
validator: $.optional.either($.bool, $.str),
default: false,
transform: (v: any): boolean => v === true || v === 'true',
desc: {
@ -54,6 +56,10 @@ export const meta = {
}
},
res: {
type: 'DriveFile',
},
errors: {
invalidFileName: {
message: 'Invalid file name.',

View file

@ -14,6 +14,8 @@ export const meta = {
'en-US': 'Delete a file of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-write',

View file

@ -6,6 +6,8 @@ import define from '../../../define';
export const meta = {
requireCredential: true,
tags: ['drive'],
kind: 'drive-read',
params: {

View file

@ -14,6 +14,8 @@ export const meta = {
'en-US': 'Get specified file of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',
@ -37,6 +39,10 @@ export const meta = {
}
},
res: {
type: 'DriveFile',
},
errors: {
noSuchFile: {
message: 'No such file.',

View file

@ -13,6 +13,8 @@ export const meta = {
'en-US': 'Update specified file of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-write',

View file

@ -10,6 +10,8 @@ export const meta = {
'ja-JP': 'ドライブに指定されたURLに存在するファイルをアップロードします。'
},
tags: ['drive'],
limit: {
duration: ms('1hour'),
max: 60

View file

@ -9,6 +9,8 @@ export const meta = {
'en-US': 'Get folders of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',

View file

@ -13,6 +13,8 @@ export const meta = {
'en-US': 'Create a folder of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-write',

View file

@ -14,6 +14,8 @@ export const meta = {
'en-US': 'Delete specified folder of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-write',

View file

@ -4,6 +4,8 @@ import DriveFolder, { pack } from '../../../../../models/drive-folder';
import define from '../../../define';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',

View file

@ -12,6 +12,8 @@ export const meta = {
'en-US': 'Get specified folder of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',

View file

@ -13,6 +13,8 @@ export const meta = {
'en-US': 'Update specified folder of drive.'
},
tags: ['drive'],
requireCredential: true,
kind: 'drive-write',

View file

@ -4,6 +4,8 @@ import DriveFile, { packMany } from '../../../../models/drive-file';
import define from '../../define';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'drive-read',

View file

@ -3,6 +3,8 @@ import define from '../../define';
import Instance from '../../../../models/instance';
export const meta = {
tags: ['federation'],
requireCredential: false,
params: {

View file

@ -3,6 +3,8 @@ import define from '../../define';
import Instance from '../../../../models/instance';
export const meta = {
tags: ['federation'],
requireCredential: false,
params: {

View file

@ -16,6 +16,8 @@ export const meta = {
'en-US': 'Follow a user.'
},
tags: ['following', 'users'],
limit: {
duration: ms('1hour'),
max: 100

View file

@ -16,6 +16,8 @@ export const meta = {
'en-US': 'Unfollow a user.'
},
tags: ['following', 'users'],
limit: {
duration: ms('1hour'),
max: 100

View file

@ -11,6 +11,8 @@ export const meta = {
'en-US': 'Accept a follow request.'
},
tags: ['following', 'account'],
requireCredential: true,
kind: 'following-write',

View file

@ -12,6 +12,8 @@ export const meta = {
'en-US': 'Cancel a follow request.'
},
tags: ['following', 'account'],
requireCredential: true,
kind: 'following-write',

View file

@ -7,6 +7,8 @@ export const meta = {
'en-US': 'Get all pending received follow requests.'
},
tags: ['following', 'account'],
requireCredential: true,
kind: 'following-read'

View file

@ -11,6 +11,8 @@ export const meta = {
'en-US': 'Reject a follow request.'
},
tags: ['following', 'account'],
requireCredential: true,
kind: 'following-write',

View file

@ -4,6 +4,8 @@ import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
import define from '../../../define';
export const meta = {
tags: ['games'],
params: {
limit: {
validator: $.optional.num.range(1, 100),

View file

@ -6,6 +6,8 @@ import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = {
tags: ['games'],
params: {
gameId: {
validator: $.type(ID),

View file

@ -6,6 +6,8 @@ import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = {
tags: ['games'],
desc: {
'ja-JP': '指定したリバーシの対局で投了します。'
},

View file

@ -2,6 +2,8 @@ import Matching, { pack as packMatching } from '../../../../../models/games/reve
import define from '../../../define';
export const meta = {
tags: ['games'],
requireCredential: true
};

View file

@ -9,6 +9,8 @@ import { ApiError } from '../../../error';
import { getUser } from '../../../common/getters';
export const meta = {
tags: ['games'],
requireCredential: true,
params: {

View file

@ -2,6 +2,8 @@ import Matching from '../../../../../../models/games/reversi/matching';
import define from '../../../../define';
export const meta = {
tags: ['games'],
requireCredential: true
};

View file

@ -3,6 +3,8 @@ import define from '../../define';
import Hashtag from '../../../../models/hashtag';
export const meta = {
tags: ['hashtags'],
requireCredential: false,
params: {

Some files were not shown because too many files have changed in this diff Show more