summaryrefslogtreecommitdiff
path: root/src/docs
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2018-08-01 08:34:22 +0900
committerGitHub <noreply@github.com>2018-08-01 08:34:22 +0900
commit77faf7a84cc28d9a24803940730e59706edd4ec8 (patch)
treea3a366deedc99a98bcfe7358eb48aff0ff5fe71c /src/docs
parentNew translations ja.yml (English) (diff)
parentMerge pull request #2033 from syuilo/greenkeeper/qrcode-1.2.2 (diff)
downloadmisskey-77faf7a84cc28d9a24803940730e59706edd4ec8.tar.gz
misskey-77faf7a84cc28d9a24803940730e59706edd4ec8.tar.bz2
misskey-77faf7a84cc28d9a24803940730e59706edd4ec8.zip
Merge branch 'master' into l10n_master
Diffstat (limited to 'src/docs')
-rw-r--r--src/docs/about.en.md3
-rw-r--r--src/docs/about.ja.md3
-rw-r--r--src/docs/api.ja.md80
-rw-r--r--src/docs/api/endpoints/style.styl23
-rw-r--r--src/docs/api/endpoints/view.pug76
-rw-r--r--src/docs/api/entities/drive-file.yaml90
-rw-r--r--src/docs/api/entities/note.yaml190
-rw-r--r--src/docs/api/entities/style.styl1
-rw-r--r--src/docs/api/entities/user.yaml174
-rw-r--r--src/docs/api/entities/view.pug20
-rw-r--r--src/docs/api/mixins.pug34
-rw-r--r--src/docs/api/style.styl11
-rw-r--r--src/docs/article.pug9
-rw-r--r--src/docs/base.pug61
-rw-r--r--src/docs/follow.ja.md8
-rw-r--r--src/docs/mute.ja.md13
-rw-r--r--src/docs/reversi-bot.ja.md165
-rw-r--r--src/docs/stream.ja.md183
-rw-r--r--src/docs/style.styl130
-rw-r--r--src/docs/timelines.ja.md15
-rw-r--r--src/docs/ui.styl19
21 files changed, 1308 insertions, 0 deletions
diff --git a/src/docs/about.en.md b/src/docs/about.en.md
new file mode 100644
index 0000000000..bb1c51927b
--- /dev/null
+++ b/src/docs/about.en.md
@@ -0,0 +1,3 @@
+# About Misskey
+
+Misskey is a mini blog SNS.
diff --git a/src/docs/about.ja.md b/src/docs/about.ja.md
new file mode 100644
index 0000000000..1b06361f0f
--- /dev/null
+++ b/src/docs/about.ja.md
@@ -0,0 +1,3 @@
+# Misskeyについて
+
+MisskeyはミニブログSNSです。
diff --git a/src/docs/api.ja.md b/src/docs/api.ja.md
new file mode 100644
index 0000000000..ecc80cc05e
--- /dev/null
+++ b/src/docs/api.ja.md
@@ -0,0 +1,80 @@
+# Misskey API
+
+MisskeyのWeb APIを使って、プログラムからMisskeyの様々な機能にアクセスすることができます。
+APIを自分のアカウントから利用する場合(自分のアカウントのみ操作したい場合)と、アプリケーションから利用する場合(不特定のアカウントを操作したい場合)とで利用手順が異なりますので、それぞれのケースについて説明します。
+
+## 自分の所有するアカウントからAPIにアクセスする場合
+「設定 > API」で、APIにアクセスするのに必要なAPIキーを取得してください。
+APIにアクセスする際には、リクエストにAPIキーを「i」というパラメータ名で含めます。
+
+<div class="ui info warn">
+ <p><i class="fas fa-exclamation-triangle"></i> アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。</p>
+</div>
+
+APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。
+
+## アプリケーションからAPIにアクセスする場合
+直接ユーザーのAPIキーをアプリケーションが扱うのは危険なので、
+アプリケーションからAPIを利用する際には、アプリケーションとアプリケーションを利用するユーザーが結び付けられた専用のトークン(アクセストークン)をMisskeyに発行してもらい、
+そのトークンをリクエストのパラメータに含める必要があります。
+
+<div class="ui info">
+ <p><i class="fas fa-info-circle"></i> アクセストークンは、ユーザーが自分のアカウントにあなたのアプリケーションがアクセスすることを許可した場合のみ発行されます</p>
+</div>
+
+### 1.アプリケーションを登録する
+まず、あなたのアプリケーションやWebサービス(以後、あなたのアプリと呼びます)をMisskeyに登録します。
+[デベロッパーセンター](/dev)にアクセスし、「アプリ > アプリ作成」からアプリを作成してください。
+フォームの記入欄の説明は以下の通りです:
+
+| 名前 | 説明 |
+|---|---|
+| アプリケーション名 | あなたのアプリの名称。 |
+| アプリの概要 | あなたのアプリの簡単な説明や紹介。 |
+| コールバックURL | ユーザーが後述する認証フォームで認証を終えた際にリダイレクトするURLを設定できます。あなたのアプリがWebサービスである場合に有用です。 |
+| 権限 | あなたのアプリが要求する権限。ここで要求した機能だけがAPIからアクセスできます。 |
+
+登録が済むとあなたのアプリのシークレットキーが入手できます。このシークレットキーは後で使用します。
+
+<div class="ui info warn">
+ <p><i class="fas fa-exclamation-triangle"></i> アプリに成りすまされる可能性があるため、極力このシークレットキーは公開しないようにしてください。</p>
+</div>
+
+### 2.ユーザーに認証させる
+アプリを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。
+
+認証セッションを開始するには、%API_URL%/auth/session/generate へパラメータに appSecret としてシークレットキーを含めたリクエストを送信します。
+リクエスト形式はJSONで、メソッドはPOSTです。
+レスポンスとして認証セッションのトークンや認証フォームのURLが取得できるので、認証フォームのURLをブラウザで表示し、ユーザーにフォームを提示してください。
+
+あなたのアプリがコールバックURLを設定している場合、
+ユーザーがあなたのアプリの連携を許可すると設定しているコールバックURLに token という名前でセッションのトークンが含まれたクエリを付けてリダイレクトします。
+
+あなたのアプリがコールバックURLを設定していない場合、ユーザーがあなたのアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。
+
+### 3.ユーザーのアクセストークンを取得する
+ユーザーが連携を許可したら、%API_URL%/auth/session/userkey へ次のパラメータを含むリクエストを送信します:
+
+| 名前 | 型 | 説明 |
+|---|---|---|
+| appSecret | string | アプリのシークレットキー |
+| token | string | セッションのトークン |
+
+上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます!
+
+アクセストークンが取得できたら、「ユーザーのアクセストークン+あなたのアプリのシークレットキーをsha256したもの」を「i」というパラメータでリクエストに含めると、APIにアクセスすることができます。
+
+「i」パラメータの生成方法を擬似コードで表すと次のようになります:
+<pre><code>const i = sha256(accessToken + secretKey);</code></pre>
+
+APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。
+
+## Misskey APIの利用
+APIはすべてリクエストのパラメータ・レスポンスともにJSON形式です。また、すべてのエンドポイントはPOSTメソッドのみ受け付けます。
+
+ストリーミングAPIも提供しています。
+
+APIリファレンスもご確認ください。
+
+### レートリミット
+Misskey APIにはレートリミットがあり、短時間のうちに多数のリクエストを送信すると、一定時間APIを利用することができなくなることがあります。
diff --git a/src/docs/api/endpoints/style.styl b/src/docs/api/endpoints/style.styl
new file mode 100644
index 0000000000..e7e32b3395
--- /dev/null
+++ b/src/docs/api/endpoints/style.styl
@@ -0,0 +1,23 @@
+@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
diff --git a/src/docs/api/endpoints/view.pug b/src/docs/api/endpoints/view.pug
new file mode 100644
index 0000000000..76e1183302
--- /dev/null
+++ b/src/docs/api/endpoints/view.pug
@@ -0,0 +1,76 @@
+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
+
+ if endpoint.desc
+ p#desc= endpoint.desc[lang] || endpoint.desc['ja']
+
+ 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')
diff --git a/src/docs/api/entities/drive-file.yaml b/src/docs/api/entities/drive-file.yaml
new file mode 100644
index 0000000000..2d14c6e1f5
--- /dev/null
+++ b/src/docs/api/entities/drive-file.yaml
@@ -0,0 +1,90 @@
+name: "DriveFile"
+
+desc:
+ ja: "ドライブのファイル。"
+ en: "A file of Drive."
+
+props:
+ id:
+ type: "id"
+ optional: false
+ desc:
+ ja: "ファイルID"
+ en: "The ID of this file"
+
+ createdAt:
+ type: "date"
+ optional: false
+ desc:
+ ja: "アップロード日時"
+ en: "The upload date of this file"
+
+ userId:
+ type: "id(User)"
+ optional: false
+ desc:
+ ja: "所有者ID"
+ en: "The ID of the owner of this file"
+
+ user:
+ type: "entity(User)"
+ optional: true
+ desc:
+ ja: "所有者"
+ en: "The owner of this file"
+
+ name:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ファイル名"
+ en: "The name of this file"
+
+ md5:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ファイルのMD5ハッシュ値"
+ en: "The md5 hash value of this file"
+
+ type:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ファイルの種類"
+ en: "The type of this file"
+
+ datasize:
+ type: "number"
+ optional: false
+ desc:
+ ja: "ファイルサイズ(bytes)"
+ en: "The size of this file (bytes)"
+
+ url:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ファイルのURL"
+ en: "The URL of this file"
+
+ folderId:
+ type: "id(DriveFolder)"
+ optional: true
+ desc:
+ ja: "フォルダID"
+ en: "The ID of the folder of this file"
+
+ folder:
+ type: "entity(DriveFolder)"
+ optional: true
+ desc:
+ ja: "フォルダ"
+ en: "The folder of this file"
+
+ sensitive:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "このメディアが「閲覧注意」(NSFW)かどうか"
+ en: "Whether this media is NSFW"
diff --git a/src/docs/api/entities/note.yaml b/src/docs/api/entities/note.yaml
new file mode 100644
index 0000000000..04cb3c9824
--- /dev/null
+++ b/src/docs/api/entities/note.yaml
@@ -0,0 +1,190 @@
+name: "Note"
+
+desc:
+ ja: "投稿。"
+ en: "A note."
+
+props:
+ id:
+ type: "id"
+ optional: false
+ desc:
+ ja: "投稿ID"
+ en: "The ID of this note"
+
+ createdAt:
+ type: "date"
+ optional: false
+ desc:
+ ja: "投稿日時"
+ en: "The posted date of this note"
+
+ viaMobile:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "モバイル端末から投稿したか否か(自己申告であることに留意)"
+ en: "Whether this note sent via a mobile device"
+
+ text:
+ type: "string"
+ optional: true
+ desc:
+ ja: "投稿の本文"
+ en: "The text of this note"
+
+ mediaIds:
+ type: "id(DriveFile)[]"
+ optional: true
+ desc:
+ ja: "添付されているメディアのID (なければレスポンスでは空配列)"
+ en: "The IDs of the attached media (empty array for response if no media is attached)"
+
+ media:
+ type: "entity(DriveFile)[]"
+ optional: true
+ desc:
+ ja: "添付されているメディア"
+ en: "The attached media"
+
+ userId:
+ type: "id(User)"
+ optional: false
+ desc:
+ ja: "投稿者ID"
+ en: "The ID of author of this note"
+
+ user:
+ type: "entity(User)"
+ optional: true
+ desc:
+ ja: "投稿者"
+ en: "The author of this note"
+
+ myReaction:
+ type: "string"
+ optional: true
+ desc:
+ ja: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>"
+ en: "The your <a href='/docs/api/reactions'>reaction</a> of this note"
+
+ reactionCounts:
+ type: "object"
+ optional: false
+ desc:
+ ja: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト"
+
+ replyId:
+ type: "id(Note)"
+ optional: true
+ desc:
+ ja: "返信した投稿のID"
+ en: "The ID of the replyed note"
+
+ reply:
+ type: "entity(Note)"
+ optional: true
+ desc:
+ ja: "返信した投稿"
+ en: "The replyed note"
+
+ renoteId:
+ type: "id(Note)"
+ optional: true
+ desc:
+ ja: "引用した投稿のID"
+ en: "The ID of the quoted note"
+
+ renote:
+ type: "entity(Note)"
+ optional: true
+ desc:
+ ja: "引用した投稿"
+ en: "The quoted note"
+
+ poll:
+ type: "object"
+ optional: true
+ desc:
+ ja: "投票"
+ en: "The poll"
+
+ props:
+ choices:
+ type: "object[]"
+ optional: false
+ desc:
+ ja: "投票の選択肢"
+ en: "The choices of this poll"
+
+ props:
+ id:
+ type: "number"
+ optional: false
+ desc:
+ ja: "選択肢ID"
+ en: "The ID of this choice"
+
+ isVoted:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "自分がこの選択肢に投票したかどうか"
+ en: "Whether you voted to this choice"
+
+ text:
+ type: "string"
+ optional: false
+ desc:
+ ja: "選択肢本文"
+ en: "The text of this choice"
+
+ votes:
+ type: "number"
+ optional: false
+ desc:
+ ja: "この選択肢に投票された数"
+ en: "The number voted for this choice"
+ geo:
+ type: "object"
+ optional: true
+ desc:
+ ja: "位置情報"
+ en: "Geo location"
+
+ props:
+ coordinates:
+ type: "number[]"
+ optional: false
+ desc:
+ ja: "座標。最初に経度:-180〜180で表す。最後に緯度:-90〜90で表す。"
+
+ altitude:
+ type: "number"
+ optional: false
+ desc:
+ ja: "高度。メートル単位で表す。"
+
+ accuracy:
+ type: "number"
+ optional: false
+ desc:
+ ja: "緯度、経度の精度。メートル単位で表す。"
+
+ altitudeAccuracy:
+ type: "number"
+ optional: false
+ desc:
+ ja: "高度の精度。メートル単位で表す。"
+
+ heading:
+ type: "number"
+ optional: false
+ desc:
+ ja: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。"
+
+ speed:
+ type: "number"
+ optional: false
+ desc:
+ ja: "速度。メートル / 秒数で表す。"
diff --git a/src/docs/api/entities/style.styl b/src/docs/api/entities/style.styl
new file mode 100644
index 0000000000..bddf0f53ab
--- /dev/null
+++ b/src/docs/api/entities/style.styl
@@ -0,0 +1 @@
+@import "../style"
diff --git a/src/docs/api/entities/user.yaml b/src/docs/api/entities/user.yaml
new file mode 100644
index 0000000000..c245974568
--- /dev/null
+++ b/src/docs/api/entities/user.yaml
@@ -0,0 +1,174 @@
+name: "User"
+
+desc:
+ ja: "ユーザー。"
+ en: "A user."
+
+props:
+ id:
+ type: "id"
+ optional: false
+ desc:
+ ja: "ユーザーID"
+ en: "The ID of this user"
+
+ createdAt:
+ type: "date"
+ optional: false
+ desc:
+ ja: "アカウント作成日時"
+ en: "The registered date of this user"
+
+ username:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ユーザー名"
+ en: "The username of this user"
+
+ description:
+ type: "string"
+ optional: false
+ desc:
+ ja: "アカウントの説明(自己紹介)"
+ en: "The description of this user"
+
+ avatarId:
+ type: "id(DriveFile)"
+ optional: true
+ desc:
+ ja: "アバターのID"
+ en: "The ID of the avatar of this user"
+
+ avatarUrl:
+ type: "string"
+ optional: false
+ desc:
+ ja: "アバターのURL"
+ en: "The URL of the avatar of this user"
+
+ bannerId:
+ type: "id(DriveFile)"
+ optional: true
+ desc:
+ ja: "バナーのID"
+ en: "The ID of the banner of this user"
+
+ bannerUrl:
+ type: "string"
+ optional: false
+ desc:
+ ja: "バナーのURL"
+ en: "The URL of the banner of this user"
+
+ followersCount:
+ type: "number"
+ optional: false
+ desc:
+ ja: "フォロワーの数"
+ en: "The number of the followers for this user"
+
+ followingCount:
+ type: "number"
+ optional: false
+ desc:
+ ja: "フォローしているユーザーの数"
+ en: "The number of the following users for this user"
+
+ isFollowing:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "自分がこのユーザーをフォローしているか"
+
+ isFollowed:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "自分がこのユーザーにフォローされているか"
+
+ isMuted:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "自分がこのユーザーをミュートしているか"
+ en: "Whether you muted this user"
+
+ notesCount:
+ type: "number"
+ optional: false
+ desc:
+ ja: "投稿の数"
+ en: "The number of the notes of this user"
+
+ pinnedNote:
+ type: "entity(Note)"
+ optional: true
+ desc:
+ ja: "ピン留めされた投稿"
+ en: "The pinned note of this user"
+
+ pinnedNoteId:
+ type: "id(Note)"
+ optional: true
+ desc:
+ ja: "ピン留めされた投稿のID"
+ en: "The ID of the pinned note of this user"
+
+ host:
+ type: "string | null"
+ optional: false
+ desc:
+ ja: "ホスト (例: example.com:3000)"
+ en: "Host (e.g. example.com:3000)"
+
+ twitter:
+ type: "object"
+ optional: true
+ desc:
+ ja: "連携されているTwitterアカウント情報"
+ en: "The info of the connected twitter account of this user"
+
+ props:
+ userId:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ユーザーID"
+ en: "The user ID"
+
+ screenName:
+ type: "string"
+ optional: false
+ desc:
+ ja: "ユーザー名"
+ en: "The screen name of this user"
+
+ isBot:
+ type: "boolean"
+ optional: true
+ desc:
+ ja: "botか否か(自己申告であることに留意)"
+ en: "Whether is bot or not"
+
+ profile:
+ type: "object"
+ optional: false
+ desc:
+ ja: "プロフィール"
+ en: "The profile of this user"
+
+ props:
+ location:
+ type: "string"
+ optional: true
+ desc:
+ ja: "場所"
+ en: "The location of this user"
+
+ birthday:
+ type: "string"
+ optional: true
+ desc:
+ ja: "誕生日 (YYYY-MM-DD)"
+ en: "The birthday of this user (YYYY-MM-DD)"
diff --git a/src/docs/api/entities/view.pug b/src/docs/api/entities/view.pug
new file mode 100644
index 0000000000..d5c192f438
--- /dev/null
+++ b/src/docs/api/entities/view.pug
@@ -0,0 +1,20 @@
+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']
+
+ 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)
diff --git a/src/docs/api/mixins.pug b/src/docs/api/mixins.pug
new file mode 100644
index 0000000000..925aab2934
--- /dev/null
+++ b/src/docs/api/mixins.pug
@@ -0,0 +1,34 @@
+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'] : null
diff --git a/src/docs/api/style.styl b/src/docs/api/style.styl
new file mode 100644
index 0000000000..3675a4da6f
--- /dev/null
+++ b/src/docs/api/style.styl
@@ -0,0 +1,11 @@
+@import "../style"
+
+table.props
+ .name
+ font-weight bold
+
+ .name
+ .type
+ .optional
+ font-family Consolas, 'Courier New', Courier, Monaco, monospace
+
diff --git a/src/docs/article.pug b/src/docs/article.pug
new file mode 100644
index 0000000000..38494fec6c
--- /dev/null
+++ b/src/docs/article.pug
@@ -0,0 +1,9 @@
+extends ./base
+
+block main
+ != html
+
+block footer
+ p
+ = i18n('docs.edit-this-page-on-github')
+ a(href=src target="_blank")= i18n('docs.edit-this-page-on-github-link')
diff --git a/src/docs/base.pug b/src/docs/base.pug
new file mode 100644
index 0000000000..aeafaeffff
--- /dev/null
+++ b/src/docs/base.pug
@@ -0,0 +1,61 @@
+doctype html
+
+html(lang= lang)
+ head
+ meta(charset="UTF-8")
+ meta(name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no")
+ title
+ | #{title} | Misskey Docs
+ link(rel="stylesheet" href="/docs/assets/style.css")
+ link(rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css")
+ script(src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js")
+ link(rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous")
+ block meta
+
+ body
+ nav
+ ul
+ each doc in docs
+ li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja']
+ 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
+ if content
+ | !{content}
+
+ aside.
+ <div id="disqus_thread"></div>
+ <script>
+
+ /**
+ * RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
+ * LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
+ /*
+ var disqus_config = function () {
+ this.page.url = PAGE_URL; // Replace PAGE_URL with your page's canonical URL variable
+ this.page.identifier = "#{ id }"; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
+ };
+ */
+ (function() { // DON'T EDIT BELOW THIS LINE
+ var d = document, s = d.createElement('script');
+ s.src = 'https://misskey.disqus.com/embed.js';
+ s.setAttribute('data-timestamp', +new Date());
+ (d.head || d.body).appendChild(s);
+ })();
+ </script>
+ <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
+
+ footer
+ block footer
+ small= copyright
diff --git a/src/docs/follow.ja.md b/src/docs/follow.ja.md
new file mode 100644
index 0000000000..a883435ab4
--- /dev/null
+++ b/src/docs/follow.ja.md
@@ -0,0 +1,8 @@
+# フォロー
+ユーザーをフォローすると、タイムラインにそのユーザーの投稿が表示されるようになります。ただし、他のユーザーに対する返信は含まれません。
+ユーザーをフォローするには、ユーザーページの「フォロー」ボタンをクリックします。フォローを解除するには、もう一度クリックします。
+
+## ストーキング
+ユーザーをフォローしている状態では、さらに「ストーキング」モードをオンにすることができます。ストーキングを行うと、タイムラインにそのユーザーの全ての投稿が表示されるようになります。つまり、他のユーザーに対する返信も含まれることになります。
+ストーキングするには、ユーザーページの「ストークする」をクリックします。ストーキングをやめるには、もう一度クリックします。
+ストーキングしていることは相手に通知されません。
diff --git a/src/docs/mute.ja.md b/src/docs/mute.ja.md
new file mode 100644
index 0000000000..6a9608662a
--- /dev/null
+++ b/src/docs/mute.ja.md
@@ -0,0 +1,13 @@
+# ミュート
+
+ユーザーをミュートすると、そのユーザーに関する次のコンテンツがMisskeyに表示されなくなります:
+
+* タイムラインや投稿の検索結果内の、そのユーザーの投稿(およびそれらの投稿に対する返信やRenote)
+* そのユーザーからの通知
+* メッセージ履歴一覧内の、そのユーザーとのメッセージ履歴
+
+ユーザーをミュートするには、対象のユーザーのユーザーページに表示されている「ミュート」ボタンを押します。
+
+ミュートを行ったことは相手に通知されず、ミュートされていることを知ることもできません。
+
+設定>ミュート から、自分がミュートしているユーザー一覧を確認することができます。
diff --git a/src/docs/reversi-bot.ja.md b/src/docs/reversi-bot.ja.md
new file mode 100644
index 0000000000..6fe62003df
--- /dev/null
+++ b/src/docs/reversi-bot.ja.md
@@ -0,0 +1,165 @@
+# MisskeyリバーシBotの開発
+Misskeyのリバーシ機能に対応したBotの開発方法をここに記します。
+
+1. `reversi`ストリームに以下のパラメータを付けて接続する:
+ * `i`: botアカウントのAPIキー
+
+2. 対局への招待が来たら、ストリームから`invited`イベントが流れてくる
+ * イベントの中身に、`parent`という名前で対局へ誘ってきたユーザーの情報が含まれている
+
+3. `reversi/match`へ、`user_id`として`parent`の`id`が含まれたリクエストを送信する
+
+4. 上手くいくとゲーム情報が返ってくるので、`reversi-game`ストリームへ、以下のパラメータを付けて接続する:
+ * `i`: botアカウントのAPIキー
+ * `game`: `game`の`id`
+
+5. この間、相手がゲームの設定を変更するとその都度`update-settings`イベントが流れてくるので、必要であれば何かしらの処理を行う
+
+6. 設定に満足したら、`{ type: 'accept' }`メッセージをストリームに送信する
+
+7. ゲームが開始すると、`started`イベントが流れてくる
+ * イベントの中身にはゲーム情報が含まれている
+
+8. 石を打つには、ストリームに`{ type: 'set', pos: <位置> }`を送信する(位置の計算方法は後述)
+
+9. 相手または自分が石を打つと、ストリームから`set`イベントが流れてくる
+ * `color`として石の色が含まれている
+ * `pos`として位置情報が含まれている
+
+## 位置の計算法
+8x8のマップを考える場合、各マスの位置(Posと呼びます)は次のようになっています:
+```
++--+--+--+--+--+--+--+--+
+| 0| 1| 2| 3| 4| 5| 6| 7|
++--+--+--+--+--+--+--+--+
+| 8| 9|10|11|12|13|14|15|
++--+--+--+--+--+--+--+--+
+|16|17|18|19|20|21|22|23|
+...
+```
+
+### X,Y座標 から Pos に変換する
+```
+pos = x + (y * mapWidth)
+```
+`mapWidth`は、ゲーム情報の`settings.map`から、次のようにして計算できます:
+```
+mapWidth = settings.map[0].length
+```
+
+### Pos から X,Y座標 に変換する
+```
+x = pos % mapWidth
+y = Math.floor(pos / mapWidth)
+```
+
+## マップ情報
+マップ情報は、ゲーム情報の`settings.map`に入っています。
+文字列の配列になっており、ひとつひとつの文字がマス情報を表しています。
+それをもとにマップのデザインを知る事が出来ます:
+* `(スペース)` ... マス無し
+* `-` ... マス
+* `b` ... 初期配置される黒石
+* `w` ... 初期配置される白石
+
+例えば、4*4の次のような単純なマップがあるとします:
+```text
++---+---+---+---+
+| | | | |
++---+---+---+---+
+| | ○ | ● | |
++---+---+---+---+
+| | ● | ○ | |
++---+---+---+---+
+| | | | |
++---+---+---+---+
+```
+
+この場合、マップデータはこのようになります:
+```javascript
+['----', '-wb-', '-bw-', '----']
+```
+
+## ユーザーにフォームを提示して対話可能Botを作成する
+ユーザーとのコミュニケーションを行うため、ゲームの設定画面でユーザーにフォームを提示することができます。
+例えば、Botの強さをユーザーが設定できるようにする、といったシナリオが考えられます。
+
+フォームを提示するには、`reversi-game`ストリームに次のメッセージを送信します:
+```javascript
+{
+ type: 'init-form',
+ body: [フォームコントロールの配列]
+}
+```
+
+フォームコントロールの配列については今から説明します。
+フォームコントロールは、次のようなオブジェクトです:
+```javascript
+{
+ id: 'button1',
+ type: 'button',
+ label: 'Enable hoge',
+ value: false
+}
+```
+`id` ... コントロールのID。
+`type` ... コントロールの種類。後述します。
+`label` ... コントロールと一緒に表記するテキスト。
+`value` ... コントロールのデフォルト値。
+
+### フォームの操作を受け取る
+ユーザーがフォームを操作すると、ストリームから`update-form`イベントが流れてきます。
+イベントの中身には、コントロールのIDと、ユーザーが設定した値が含まれています。
+例えば、上で示したボタンをユーザーがオンにしたとすると、次のイベントが流れてきます:
+```javascript
+{
+ id: 'button1',
+ value: true
+}
+```
+
+### フォームコントロールの種類
+#### ボタン
+type: `button`
+ボタンを表示します。何かの機能をオン/オフさせたい場合に有用です。
+
+##### プロパティ
+`desc` ... ボタンの詳細な説明。
+
+#### ラジオボタン
+type: `radio`
+ラジオボタンを表示します。選択肢を提示するのに有用です。例えば、Botの強さを設定させるなどです。
+
+##### プロパティ
+`items` ... ラジオボタンの選択肢。例:
+```javascript
+items: [{
+ label: '弱',
+ value: 1
+}, {
+ label: '中',
+ value: 2
+}, {
+ label: '強',
+ value: 3
+}]
+```
+
+#### テキストボックス
+type: `textbox`
+テキストボックスを表示します。ユーザーになにか入力させる一般的な用途に利用できます。
+
+## ユーザーにメッセージを表示する
+設定画面でユーザーと対話する、フォーム以外のもうひとつの方法がこれです。ユーザーになにかメッセージを表示することができます。
+例えば、ユーザーがBotの対応していないモードやマップを選択したとき、警告を表示するなどです。
+メッセージを表示するには、次のメッセージをストリームに送信します:
+```javascript
+{
+ type: 'message',
+ body: {
+ text: 'メッセージ内容',
+ type: 'メッセージの種類'
+ }
+}
+```
+メッセージの種類: `success`, `info`, `warning`, `error`。
diff --git a/src/docs/stream.ja.md b/src/docs/stream.ja.md
new file mode 100644
index 0000000000..c720299932
--- /dev/null
+++ b/src/docs/stream.ja.md
@@ -0,0 +1,183 @@
+# ストリーミングAPI
+
+ストリーミングAPIを使うと、リアルタイムで様々な情報(例えばタイムラインに新しい投稿が流れてきた、メッセージが届いた、フォローされた、など)を受け取ったり、HTTPリクエストを発生させることなくAPIにアクセスしたりすることができます。
+
+ストリーミングAPIは複数の種類がありますが、ここではメインとなる「ホームストリーム」について説明します。
+
+## ストリームに接続する
+
+以下のURLに**websocket**接続します。
+```
+%URL%
+```
+
+接続する際は、`i`というパラメータ名で認証情報を含めます。例:
+```
+%URL%/?i=xxxxxxxxxxxxxxx
+```
+
+認証情報は、自分のAPIキーや、アプリケーションからストリームに接続する際はユーザーのアクセストークンのことを指します。
+
+<div class="ui info">
+ <p><i class="fas fa-info-circle"></i> 認証情報の取得については、<a href="./api">こちらのドキュメント</a>をご確認ください。</p>
+</div>
+
+
+## ストリームを経由してAPIリクエストする
+
+ストリームを経由してAPIリクエストすると、HTTPリクエストを発生させずにAPIを利用できます。そのため、コードを簡潔にできたり、パフォーマンスの向上を見込めるかもしれません。
+
+ストリームを経由してAPIリクエストするには、次のようなメッセージをストリームに送信します:
+```json
+{
+ type: 'api',
+ id: 'xxxxxxxxxxxxxxxx',
+ endpoint: 'notes/create',
+ data: {
+ text: 'yee haw!'
+ }
+}
+```
+
+`id`には、APIのレスポンスを識別するための、APIリクエストごとの一意なIDを設定する必要があります。UUIDや、簡単な乱数のようなもので構いません。
+
+`endpoint`には、あなたがリクエストしたいAPIのエンドポイントを指定します。
+
+`data`には、エンドポイントのパラメータを含めます。
+
+<div class="ui info">
+ <p><i class="fas fa-info-circle"></i> APIのエンドポイントやパラメータについてはAPIリファレンスをご確認ください。</p>
+</div>
+
+### レスポンスの受信
+
+APIへリクエストすると、レスポンスがストリームから次のような形式で流れてきます。
+
+```json
+{
+ type: 'api-res:xxxxxxxxxxxxxxxx',
+ body: {
+ ...
+ }
+}
+```
+
+`xxxxxxxxxxxxxxxx`の部分には、リクエストの際に設定された`id`が含まれています。これにより、どのリクエストに対するレスポンスなのか判別することができます。
+
+`body`には、レスポンスが含まれています。
+
+## 投稿のキャプチャ
+
+Misskeyは投稿のキャプチャと呼ばれる仕組みを提供しています。これは、指定した投稿のイベントをストリームで受け取る機能です。
+
+例えばタイムラインを取得してユーザーに表示したとします。ここで誰かがそのタイムラインに含まれるどれかの投稿に対してリアクションしたとします。
+
+しかし、クライアントからするとある投稿にリアクションが付いたことなどは知る由がないため、リアルタイムでリアクションをタイムライン上の投稿に反映して表示するといったことができません。
+
+この問題を解決するために、Misskeyは投稿のキャプチャ機構を用意しています。投稿をキャプチャすると、その投稿に関するイベントを受け取ることができるため、リアルタイムでリアクションを反映させたりすることが可能になります。
+
+### 投稿をキャプチャする
+
+投稿をキャプチャするには、ストリームに次のようなメッセージを送信します:
+
+```json
+{
+ type: 'capture',
+ id: 'xxxxxxxxxxxxxxxx'
+}
+```
+
+`id`には、キャプチャしたい投稿の`id`を設定します。
+
+このメッセージを送信すると、Misskeyにキャプチャを要請したことになり、以後、その投稿に関するイベントが流れてくるようになります。
+
+例えば投稿にリアクションが付いたとすると、次のようなメッセージが流れてきます:
+
+```json
+{
+ type: 'note-updated',
+ body: {
+ note: {
+ ...
+ }
+ }
+}
+```
+
+`body`内の`note`には、その投稿の最新の情報が含まれています。
+
+---
+
+このように、投稿の情報が更新されると、`note-updated`イベントが流れてくるようになります。`note-updated`イベントが発生するのは、以下の場合です:
+
+- 投稿にリアクションが付いた
+- 投稿に添付されたアンケートに投票がされた
+- 投稿が削除された
+
+### 投稿のキャプチャを解除する
+
+その投稿がもう画面に表示されなくなったりして、その投稿に関するイベントをもう受け取る必要がなくなったときは、キャプチャの解除を申請してください。
+
+次のメッセージを送信します:
+
+```json
+{
+ type: 'decapture',
+ id: 'xxxxxxxxxxxxxxxx'
+}
+```
+
+`id`には、キャプチャを解除したい投稿の`id`を設定します。
+
+このメッセージを送信すると、以後、その投稿に関するイベントは流れてこないようになります。
+
+## 流れてくるイベント一覧
+
+流れてくるすべてのメッセージはJSON形式で、必ず`type`というプロパティが含まれています。これにより、メッセージの種類(イベント)を判別することができます。
+
+### `note`
+
+タイムラインに新しい投稿が流れてきたときに発生するイベントです。
+
+`body`プロパティの中に、投稿情報が含まれています。
+
+### `renote`
+
+自分の投稿がRenoteされた時に発生するイベントです。自分自身の投稿をRenoteしたときは発生しません。
+
+`body`プロパティの中に、Renoteされた投稿情報が含まれています。
+
+### `mention`
+
+誰かからメンションされたときに発生するイベントです。
+
+`body`プロパティの中に、投稿情報が含まれています。
+
+### `read_all_notifications`
+
+自分宛ての通知がすべて既読になったことを表すイベントです。このイベントを利用して、「通知があることを示すアイコン」のようなものをオフにしたりする等のケースが想定されます。
+
+### `meUpdated`
+
+自分の情報が更新されたことを表すイベントです。
+
+`body`プロパティの中に、最新の自分のアカウントの情報が含まれています。
+
+### `follow`
+
+自分が誰かをフォローしたときに発生するイベントです。
+
+`body`プロパティの中に、フォローしたユーザーの情報が含まれています。
+
+### `unfollow`
+
+自分が誰かのフォローを解除したときに発生するイベントです。
+
+`body`プロパティの中に、フォロー解除したユーザーの情報が含まれています。
+
+### `followed`
+
+自分が誰かにフォローされたときに発生するイベントです。
+
+`body`プロパティの中に、フォローしてきたユーザーの情報が含まれています。
+
diff --git a/src/docs/style.styl b/src/docs/style.styl
new file mode 100644
index 0000000000..b01fe493ac
--- /dev/null
+++ b/src/docs/style.styl
@@ -0,0 +1,130 @@
+@import "../client/style"
+@import "./ui"
+
+body
+ margin 0
+ color #34495e
+ word-break break-word
+
+main
+ margin 0 0 0 330px
+ padding 64px
+ width 850px
+ max-width calc(100% - 330px)
+
+ h1
+ margin 0 0 24px 0
+ padding 16px 0
+ font-size 1.5em
+ border-bottom solid 2px #eee
+
+ h2
+ margin 1em 0 24px 0
+ padding 0 0 16px 0
+ font-size 1.4em
+ border-bottom solid 1px #eee
+
+ h3
+ margin 1em 0 0 0
+ padding 0
+ font-size 1.25em
+
+ h4
+ margin 1em 0 0 0
+
+ p
+ margin 1em 0
+ line-height 1.6em
+
+ hr
+ border none
+ border-bottom solid 2px #eee
+
+ > aside
+ margin-top 32px
+ padding-top 32px
+ border-top solid 2px #eee
+
+ > footer
+ margin 32px 0 0 0
+ border-top solid 2px #eee
+
+ > small
+ display block
+ margin 16px 0 0 0
+ color #aaa
+
+nav
+ display block
+ position fixed
+ z-index 10000
+ top 0
+ left 0
+ width 330px
+ height 100%
+ overflow auto
+ padding 32px
+ background #fff
+ border-right solid 2px #eee
+
+ ul
+ padding 0
+ margin 0
+
+@media (max-width 1025px)
+ main
+ margin 0
+ max-width 100%
+
+ nav
+ position relative
+ width 100%
+ max-height 128px
+ background #f9f9f9
+ border-right none
+
+@media (max-width 768px)
+ main
+ padding 32px
+
+@media (max-width 512px)
+ main
+ padding 16px
+
+table
+ width 100%
+ max-width 100%
+ overflow auto
+ border-spacing 0
+ border-collapse collapse
+
+ thead
+ font-weight bold
+ border-bottom solid 2px #eee
+
+ tr
+ th
+ text-align left
+
+ tbody
+ tr
+ &:nth-child(odd)
+ background #fbfbfb
+
+ th, td
+ padding 8px 16px
+ min-width 128px
+
+code
+ padding 4px 8px
+ font-family Consolas, 'Courier New', Courier, Monaco, monospace
+ //color #295c92
+ background #f2f2f2
+ border-radius 4px
+
+pre
+ overflow auto
+
+ > code
+ display block
+ padding 16px
diff --git a/src/docs/timelines.ja.md b/src/docs/timelines.ja.md
new file mode 100644
index 0000000000..36ba61bd2d
--- /dev/null
+++ b/src/docs/timelines.ja.md
@@ -0,0 +1,15 @@
+# タイムラインの比較
+
+https://docs.google.com/spreadsheets/d/1lxQ2ugKrhz58Bg96HTDK_2F98BUritkMyIiBkOByjHA/edit?usp=sharing
+
+## ホーム
+自分のフォローしているユーザーの投稿
+
+## ローカル
+全てのローカルユーザーの「ホーム」指定されていない投稿
+
+## ソーシャル
+自分のフォローしているユーザーの投稿と、全てのローカルユーザーの「ホーム」指定されていない投稿
+
+## グローバル
+全てのローカルユーザーの「ホーム」指定されていない投稿と、サーバーに届いた全てのリモートユーザーの「ホーム」指定されていない投稿
diff --git a/src/docs/ui.styl b/src/docs/ui.styl
new file mode 100644
index 0000000000..8d5515712f
--- /dev/null
+++ b/src/docs/ui.styl
@@ -0,0 +1,19 @@
+.ui.info
+ display block
+ margin 1em 0
+ padding 0 1em
+ font-size 90%
+ color rgba(#000, 0.87)
+ background #f8f8f9
+ border-radius 4px
+ overflow hidden
+
+ > p
+ opacity 0.8
+
+ > [data-fa]:first-child
+ margin-right 0.25em
+
+ &.warn
+ color #573a08
+ background #FFFAF3