From be52eb9b3f4d533b6dfa6d4435a6a4b96c7b5683 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sun, 15 Jul 2018 19:05:19 +0900
Subject: [PATCH] API doc

---
 src/docs/api.ja.md                | 77 +++++++++++++++++++++++++++++++
 src/docs/api/endpoints/view.pug   |  2 +-
 src/docs/api/entities/view.pug    |  2 +-
 src/docs/article.pug              |  2 +-
 src/docs/{layout.pug => base.pug} |  4 +-
 src/server/web/docs.ts            | 20 ++++++--
 6 files changed, 97 insertions(+), 10 deletions(-)
 create mode 100644 src/docs/api.ja.md
 rename src/docs/{layout.pug => base.pug} (82%)

diff --git a/src/docs/api.ja.md b/src/docs/api.ja.md
new file mode 100644
index 0000000000..22a491e4b0
--- /dev/null
+++ b/src/docs/api.ja.md
@@ -0,0 +1,77 @@
+# 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.ユーザーのアクセストークンを取得する
+ユーザーが連携を許可したら、%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リファレンスもご確認ください。
+
+### レートリミット
+Misskey APIにはレートリミットがあり、短時間のうちに多数のリクエストを送信すると、一定時間APIを利用することができなくなることがあります。
diff --git a/src/docs/api/endpoints/view.pug b/src/docs/api/endpoints/view.pug
index e046b3fc33..4daaad7717 100644
--- a/src/docs/api/endpoints/view.pug
+++ b/src/docs/api/endpoints/view.pug
@@ -1,4 +1,4 @@
-extends ../../layout.pug
+extends ../../base
 include ../mixins
 
 block meta
diff --git a/src/docs/api/entities/view.pug b/src/docs/api/entities/view.pug
index 3f50bfd3bd..d5c192f438 100644
--- a/src/docs/api/entities/view.pug
+++ b/src/docs/api/entities/view.pug
@@ -1,4 +1,4 @@
-extends ../../layout.pug
+extends ../../base
 include ../mixins
 
 block meta
diff --git a/src/docs/article.pug b/src/docs/article.pug
index fe68ceb910..cba9fc6665 100644
--- a/src/docs/article.pug
+++ b/src/docs/article.pug
@@ -1,4 +1,4 @@
-extends ./layout.pug
+extends ./base
 
 block main
 	!= html
diff --git a/src/docs/layout.pug b/src/docs/base.pug
similarity index 82%
rename from src/docs/layout.pug
rename to src/docs/base.pug
index 4186d2d365..1ee623bb3e 100644
--- a/src/docs/layout.pug
+++ b/src/docs/base.pug
@@ -7,11 +7,9 @@ html(lang= lang)
 		title
 			| #{title} | Misskey Docs
 		link(rel="stylesheet" href="/docs/assets/style.css")
+		link(rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous")
 		block meta
 
-		//- FontAwesome style
-		style #{facss}
-
 	body
 		nav
 			ul
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index 8f707d4d3f..074ef6e30f 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -13,7 +13,6 @@ import * as glob from 'glob';
 import * as yaml from 'js-yaml';
 import config from '../../config';
 import I18n from '../../misc/i18n';
-import { fa } from '../../misc/fa';
 import { licenseHtml } from '../../misc/license';
 const constants = require('../../const.json');
 
@@ -50,8 +49,6 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> {
 
 	vars['copyright'] = constants.copyright;
 
-	vars['facss'] = fa.dom.css();
-
 	vars['license'] = licenseHtml;
 
 	const i18n = new I18n(lang);
@@ -207,7 +204,22 @@ router.get('/*/*', async ctx => {
 	const lang = ctx.params[0];
 	const doc = ctx.params[1];
 
-	const conv = new showdown.Converter();
+	showdown.extension('urlExtension', () => ({
+		type: 'output',
+		regex: /%URL%/g,
+		replace: config.url
+	}));
+
+	showdown.extension('apiUrlExtension', () => ({
+		type: 'output',
+		regex: /%API_URL%/g,
+		replace: config.api_url
+	}));
+
+	const conv = new showdown.Converter({
+		tables: true,
+		extensions: ['urlExtension', 'apiUrlExtension']
+	});
 	const md = fs.readFileSync(`${__dirname}/../../../src/docs/${doc}.${lang}.md`, 'utf8');
 
 	await ctx.render('../../../../src/docs/article', Object.assign({