From 11439afde76015b80e8d2e680808161cbc1800d5 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Thu, 5 Jul 2018 23:36:07 +0900
Subject: [PATCH] wip

---
 package.json                                  |   2 +-
 src/cafy-id.ts                                |   4 +-
 src/server/api/endpoints/aggregation/posts.ts |   2 +-
 src/server/api/endpoints/aggregation/users.ts |   2 +-
 .../endpoints/aggregation/users/activity.ts   |   2 +-
 src/server/api/endpoints/app/create.ts        |   2 +-
 src/server/api/endpoints/app/show.ts          |   4 +-
 src/server/api/endpoints/drive/files.ts       |  10 +-
 .../api/endpoints/drive/files/create.ts       |   2 +-
 src/server/api/endpoints/drive/files/find.ts  |   2 +-
 .../api/endpoints/drive/files/update.ts       |   4 +-
 .../endpoints/drive/files/upload_from_url.ts  |   2 +-
 src/server/api/endpoints/drive/folders.ts     |   8 +-
 .../api/endpoints/drive/folders/create.ts     |   4 +-
 .../api/endpoints/drive/folders/find.ts       |   2 +-
 .../api/endpoints/drive/folders/update.ts     |   4 +-
 src/server/api/endpoints/drive/stream.ts      |   8 +-
 src/server/api/endpoints/i/authorized_apps.ts |   6 +-
 src/server/api/endpoints/i/favorites.ts       |   6 +-
 src/server/api/endpoints/i/notifications.ts   |  12 +-
 src/server/api/endpoints/i/signin_history.ts  |   6 +-
 src/server/api/endpoints/i/update.ts          |  22 +--
 .../api/endpoints/i/update_client_setting.ts  |   2 +-
 src/server/api/endpoints/messaging/history.ts |   2 +-
 .../api/endpoints/messaging/messages.ts       |   8 +-
 .../endpoints/messaging/messages/create.ts    |   4 +-
 src/server/api/endpoints/mute/list.ts         |   6 +-
 src/server/api/endpoints/my/apps.ts           |   4 +-
 src/server/api/endpoints/notes.ts             |  18 +--
 .../api/endpoints/notes/conversation.ts       |   4 +-
 src/server/api/endpoints/notes/create.ts      | 147 +++++++++---------
 .../api/endpoints/notes/global-timeline.ts    |  12 +-
 .../api/endpoints/notes/local-timeline.ts     |  12 +-
 src/server/api/endpoints/notes/mentions.ts    |   8 +-
 .../endpoints/notes/polls/recommendation.ts   |   4 +-
 src/server/api/endpoints/notes/reactions.ts   |   6 +-
 src/server/api/endpoints/notes/replies.ts     |   4 +-
 src/server/api/endpoints/notes/reposts.ts     |   6 +-
 src/server/api/endpoints/notes/search.ts      |   4 +-
 .../api/endpoints/notes/search_by_tag.ts      |  28 ++--
 src/server/api/endpoints/notes/timeline.ts    |  16 +-
 src/server/api/endpoints/notes/trend.ts       |  12 +-
 .../api/endpoints/notes/user-list-timeline.ts |  16 +-
 src/server/api/endpoints/reversi/games.ts     |   8 +-
 src/server/api/endpoints/users.ts             |   6 +-
 src/server/api/endpoints/users/followers.ts   |   6 +-
 src/server/api/endpoints/users/following.ts   |   6 +-
 .../users/get_frequently_replied_users.ts     |   2 +-
 src/server/api/endpoints/users/notes.ts       |  20 +--
 .../api/endpoints/users/recommendation.ts     |   4 +-
 src/server/api/endpoints/users/search.ts      |   2 +-
 .../api/endpoints/users/search_by_username.ts |   4 +-
 src/server/api/endpoints/users/show.ts        |   8 +-
 src/server/api/get-params.ts                  |  15 +-
 54 files changed, 260 insertions(+), 260 deletions(-)

diff --git a/package.json b/package.json
index b5cc2457c7..42b8fdf5e4 100644
--- a/package.json
+++ b/package.json
@@ -89,7 +89,7 @@
 		"autwh": "0.1.0",
 		"bcryptjs": "2.4.3",
 		"bootstrap-vue": "2.0.0-rc.11",
-		"cafy": "8.0.0",
+		"cafy": "11.0.0",
 		"chalk": "2.4.1",
 		"crc-32": "1.2.0",
 		"css-loader": "0.28.11",
diff --git a/src/cafy-id.ts b/src/cafy-id.ts
index dac0f97bd2..9b7f4f97bf 100644
--- a/src/cafy-id.ts
+++ b/src/cafy-id.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import { Query } from 'cafy';
+import { Context } from 'cafy';
 
 export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
 export const isNotAnId = (x: any) => !isAnId(x);
@@ -7,7 +7,7 @@ export const isNotAnId = (x: any) => !isAnId(x);
 /**
  * ID
  */
-export default class ID extends Query<mongo.ObjectID> {
+export default class ID extends Context<mongo.ObjectID> {
 	constructor() {
 		super();
 
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts
index 48e344312d..5de5789954 100644
--- a/src/server/api/endpoints/aggregation/posts.ts
+++ b/src/server/api/endpoints/aggregation/posts.ts
@@ -6,7 +6,7 @@ import Note from '../../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const datas = await Note
diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts
index c084404d0a..3ab96b66d4 100644
--- a/src/server/api/endpoints/aggregation/users.ts
+++ b/src/server/api/endpoints/aggregation/users.ts
@@ -6,7 +6,7 @@ import User from '../../../../models/user';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const users = await User
diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts
index d4c716d65b..98c7d3a1dc 100644
--- a/src/server/api/endpoints/aggregation/users/activity.ts
+++ b/src/server/api/endpoints/aggregation/users/activity.ts
@@ -9,7 +9,7 @@ import Note from '../../../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
+	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index c7bc91a079..5da87e5a3a 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -78,7 +78,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res
 
 	// Get 'callbackUrl' parameter
 	// TODO: Check it is valid url
-	const [callbackUrl = null, callbackUrlErr] = $.str.optional().nullable().get(params.callbackUrl);
+	const [callbackUrl = null, callbackUrlErr] = $.str.optional.nullable.get(params.callbackUrl);
 	if (callbackUrlErr) return rej('invalid callbackUrl param');
 
 	// Generate secret
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index 2b98a3f142..982c87c4ec 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -39,11 +39,11 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	const isSecure = user != null && app == null;
 
 	// Get 'appId' parameter
-	const [appId, appIdErr] = $.type(ID).optional().get(params.appId);
+	const [appId, appIdErr] = $.type(ID).optional.get(params.appId);
 	if (appIdErr) return rej('invalid appId param');
 
 	// Get 'nameId' parameter
-	const [nameId, nameIdErr] = $.str.optional().get(params.nameId);
+	const [nameId, nameIdErr] = $.str.optional.get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
 
 	if (appId === undefined && nameId === undefined) {
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index efce750747..fa99c4a51b 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Check if both of sinceId and untilId is specified
@@ -24,11 +24,11 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
+	const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
 	if (typeErr) throw 'invalid type param';
 
 	// Construct query
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index db2626af09..4c348c1302 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -28,7 +28,7 @@ module.exports = async (file: any, params: any, user: ILocalUser): Promise<any>
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	function cleanup() {
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index 75ab91f0a1..dfca4e0395 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index 825683b214..76656beaa0 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -24,12 +24,12 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().pipe(validateFileName).get(params.name);
+	const [name, nameErr] = $.str.optional.pipe(validateFileName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) file.filename = name;
 
 	// Get 'folderId' parameter
-	const [folderId, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	if (folderId !== undefined) {
diff --git a/src/server/api/endpoints/drive/files/upload_from_url.ts b/src/server/api/endpoints/drive/files/upload_from_url.ts
index cb617d851f..442a0d3940 100644
--- a/src/server/api/endpoints/drive/files/upload_from_url.ts
+++ b/src/server/api/endpoints/drive/files/upload_from_url.ts
@@ -16,7 +16,7 @@ module.exports = async (params: any, user: ILocalUser): Promise<any> => {
 	if (urlErr) throw 'invalid url param';
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) throw 'invalid folderId param';
 
 	return pack(await uploadFromUrl(url, user, folderId));
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index 3413778950..878c747a42 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -24,7 +24,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'folderId' parameter
-	const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId);
+	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts
index 8f06b0f668..c06a40ded3 100644
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ b/src/server/api/endpoints/drive/folders/create.ts
@@ -8,11 +8,11 @@ import { ILocalUser } from '../../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
-	const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
+	const [name = '無題のフォルダー', nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 
 	// If the parent folder is specified
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
index b3238b5c32..414202ccd6 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'parentId' parameter
-	const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 
 	// Issue query
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index f126c09f5b..20675771fe 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -23,12 +23,12 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
+	const [name, nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) folder.name = name;
 
 	// Get 'parentId' parameter
-	const [parentId, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId);
+	const [parentId, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
 	if (parentIdErr) return rej('invalid parentId param');
 	if (parentId !== undefined) {
 		if (parentId === null) {
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 515f74645a..612d922c6b 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
@@ -24,7 +24,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
+	const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
 	if (typeErr) return rej('invalid type param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index cfc93c1518..9c518b3c84 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -8,15 +8,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort);
+	const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Get tokens
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index dc343afaed..1ed42a98b1 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index ce283fe48f..93c5abf4d5 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -12,27 +12,27 @@ import { ILocalUser } from '../../../../models/user';
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
-		$.bool.optional().get(params.following);
+		$.bool.optional.get(params.following);
 	if (followingError) return rej('invalid following param');
 
 	// Get 'markAsRead' parameter
-	const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead);
+	const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
 	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'type' parameter
-	const [type, typeErr] = $.arr($.str).optional().unique().get(params.type);
+	const [type, typeErr] = $.arr($.str).optional.unique().get(params.type);
 	if (typeErr) return rej('invalid type param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts
index 4ab9881f34..e58f48f72d 100644
--- a/src/server/api/endpoints/i/signin_history.ts
+++ b/src/server/api/endpoints/i/signin_history.ts
@@ -7,15 +7,15 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 57b050ebc4..fc23d9fc82 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -14,57 +14,57 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise
 	const updates = {} as any;
 
 	// Get 'name' parameter
-	const [name, nameErr] = $.str.optional().nullable().pipe(isValidName).get(params.name);
+	const [name, nameErr] = $.str.optional.nullable.pipe(isValidName).get(params.name);
 	if (nameErr) return rej('invalid name param');
 	if (name) updates.name = name;
 
 	// Get 'description' parameter
-	const [description, descriptionErr] = $.str.optional().nullable().pipe(isValidDescription).get(params.description);
+	const [description, descriptionErr] = $.str.optional.nullable.pipe(isValidDescription).get(params.description);
 	if (descriptionErr) return rej('invalid description param');
 	if (description !== undefined) updates.description = description;
 
 	// Get 'location' parameter
-	const [location, locationErr] = $.str.optional().nullable().pipe(isValidLocation).get(params.location);
+	const [location, locationErr] = $.str.optional.nullable.pipe(isValidLocation).get(params.location);
 	if (locationErr) return rej('invalid location param');
 	if (location !== undefined) updates['profile.location'] = location;
 
 	// Get 'birthday' parameter
-	const [birthday, birthdayErr] = $.str.optional().nullable().pipe(isValidBirthday).get(params.birthday);
+	const [birthday, birthdayErr] = $.str.optional.nullable.pipe(isValidBirthday).get(params.birthday);
 	if (birthdayErr) return rej('invalid birthday param');
 	if (birthday !== undefined) updates['profile.birthday'] = birthday;
 
 	// Get 'avatarId' parameter
-	const [avatarId, avatarIdErr] = $.type(ID).optional().nullable().get(params.avatarId);
+	const [avatarId, avatarIdErr] = $.type(ID).optional.nullable.get(params.avatarId);
 	if (avatarIdErr) return rej('invalid avatarId param');
 	if (avatarId !== undefined) updates.avatarId = avatarId;
 
 	// Get 'bannerId' parameter
-	const [bannerId, bannerIdErr] = $.type(ID).optional().nullable().get(params.bannerId);
+	const [bannerId, bannerIdErr] = $.type(ID).optional.nullable.get(params.bannerId);
 	if (bannerIdErr) return rej('invalid bannerId param');
 	if (bannerId !== undefined) updates.bannerId = bannerId;
 
 	// Get 'wallpaperId' parameter
-	const [wallpaperId, wallpaperIdErr] = $.type(ID).optional().nullable().get(params.wallpaperId);
+	const [wallpaperId, wallpaperIdErr] = $.type(ID).optional.nullable.get(params.wallpaperId);
 	if (wallpaperIdErr) return rej('invalid wallpaperId param');
 	if (wallpaperId !== undefined) updates.wallpaperId = wallpaperId;
 
 	// Get 'isLocked' parameter
-	const [isLocked, isLockedErr] = $.bool.optional().get(params.isLocked);
+	const [isLocked, isLockedErr] = $.bool.optional.get(params.isLocked);
 	if (isLockedErr) return rej('invalid isLocked param');
 	if (isLocked != null) updates.isLocked = isLocked;
 
 	// Get 'isBot' parameter
-	const [isBot, isBotErr] = $.bool.optional().get(params.isBot);
+	const [isBot, isBotErr] = $.bool.optional.get(params.isBot);
 	if (isBotErr) return rej('invalid isBot param');
 	if (isBot != null) updates.isBot = isBot;
 
 	// Get 'isCat' parameter
-	const [isCat, isCatErr] = $.bool.optional().get(params.isCat);
+	const [isCat, isCatErr] = $.bool.optional.get(params.isCat);
 	if (isCatErr) return rej('invalid isCat param');
 	if (isCat != null) updates.isCat = isCat;
 
 	// Get 'autoWatch' parameter
-	const [autoWatch, autoWatchErr] = $.bool.optional().get(params.autoWatch);
+	const [autoWatch, autoWatchErr] = $.bool.optional.get(params.autoWatch);
 	if (autoWatchErr) return rej('invalid autoWatch param');
 	if (autoWatch != null) updates['settings.autoWatch'] = autoWatch;
 
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index 6d6e8ed24a..9eca66cfcc 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -11,7 +11,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res
 	if (nameErr) return rej('invalid name param');
 
 	// Get 'value' parameter
-	const [value, valueErr] = $.any.nullable().get(params.value);
+	const [value, valueErr] = $.any.nullable.get(params.value);
 	if (valueErr) return rej('invalid value param');
 
 	const x: any = {};
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index 713ba9dd7f..d76aa78230 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -9,7 +9,7 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	const mute = await Mute.find({
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index 3eb20ec06b..16236136d3 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -26,19 +26,19 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'markAsRead' parameter
-	const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead);
+	const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
 	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
index b3e4f6a8cd..d4f16d0dce 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -38,11 +38,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	}
 
 	// Get 'text' parameter
-	const [text, textErr] = $.str.optional().pipe(isValidText).get(params.text);
+	const [text, textErr] = $.str.optional.pipe(isValidText).get(params.text);
 	if (textErr) return rej('invalid text');
 
 	// Get 'fileId' parameter
-	const [fileId, fileIdErr] = $.type(ID).optional().get(params.fileId);
+	const [fileId, fileIdErr] = $.type(ID).optional.get(params.fileId);
 	if (fileIdErr) return rej('invalid fileId param');
 
 	let file = null;
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index 8b0171be33..b632b1a1a9 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -8,15 +8,15 @@ import { getFriendIds } from '../../common/get-friends';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 30, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 30, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index 7687afd0c7..8f67af8854 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -7,11 +7,11 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	const query = {
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index 5554e53aa4..8b0c4177fc 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -9,39 +9,39 @@ import Note, { pack } from '../../../models/note';
  */
 module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'local' parameter
-	const [local, localErr] = $.bool.optional().get(params.local);
+	const [local, localErr] = $.bool.optional.get(params.local);
 	if (localErr) return rej('invalid local param');
 
 	// Get 'reply' parameter
-	const [reply, replyErr] = $.bool.optional().get(params.reply);
+	const [reply, replyErr] = $.bool.optional.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote, renoteErr] = $.bool.optional().get(params.renote);
+	const [renote, renoteErr] = $.bool.optional.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media, mediaErr] = $.bool.optional().get(params.media);
+	const [media, mediaErr] = $.bool.optional.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll, pollErr] = $.bool.optional().get(params.poll);
+	const [poll, pollErr] = $.bool.optional.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	// Get 'bot' parameter
-	//const [bot, botErr] = $.bool.optional().get(params.bot);
+	//const [bot, botErr] = $.bool.optional.get(params.bot);
 	//if (botErr) return rej('invalid bot param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index b2bc6a2e72..a8e8c4eeb7 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 2bd0b430d8..043f62cf12 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -1,33 +1,83 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
 import User, { ILocalUser, IUser } from '../../../../models/user';
-import DriveFile from '../../../../models/drive-file';
+import DriveFile, { IDriveFile } from '../../../../models/drive-file';
 import create from '../../../../services/note/create';
 import { IApp } from '../../../../models/app';
 import getParams from '../../get-params';
 
 export const meta = {
 	params: {
-		visibility: {
-			def: $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']),
+		visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({
 			default: 'public',
 			desc: {
 				ja: '投稿の公開範囲'
 			}
-		},
-		visibleUserIds: {
-			def: $.arr($.type(ID)).optional().unique().min(1),
+		}),
+
+		visibleUserIds: $.arr($.type(ID)).optional.unique().min(1).note({
 			desc: {
 				ja: '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー'
 			}
-		},
-		text: {
-			def: $.str.optional().nullable().pipe(isValidText),
+		}),
+
+		text: $.str.optional.nullable.pipe(isValidText).note({
 			default: null,
 			desc: {
 				ja: '投稿内容'
 			}
-		},
+		}),
+
+		cw: $.str.optional.nullable.pipe(isValidCw).note({
+			desc: {
+				ja: 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。'
+			}
+		}),
+
+		viaMobile: $.bool.optional.note({
+			default: false,
+			desc: {
+				ja: 'モバイルデバイスからの投稿か否か。'
+			}
+		}),
+
+		geo: $.obj({
+			coordinates: $.arr().length(2)
+				.item(0, $.num.range(-180, 180))
+				.item(1, $.num.range(-90, 90)),
+			altitude: $.num.nullable,
+			accuracy: $.num.nullable,
+			altitudeAccuracy: $.num.nullable,
+			heading: $.num.nullable.range(0, 360),
+			speed: $.num.nullable
+		}).optional.nullable.strict().note({
+			desc: {
+				ja: '位置情報'
+			}
+		}),
+
+		mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
+			desc: {
+				ja: '添付するメディア'
+			}
+		}),
+
+		renoteId: $.type(ID).optional.note({
+			desc: {
+				ja: 'Renote対象'
+			}
+		}),
+
+		poll: $.obj({
+			choices: $.arr($.str)
+				.unique()
+				.range(2, 10)
+				.each(c => c.length > 0 && c.length < 50)
+		}).optional.strict().note({
+			desc: {
+				ja: 'アンケート'
+			}
+		})
 	}
 };
 
@@ -45,45 +95,12 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		})));
 	}
 
-	// Get 'text' parameter
-	const [text = null, textErr] = $.str.optional().nullable().pipe(isValidText).get(params.text);
-	if (textErr) return rej('invalid text');
-
-	// Get 'cw' parameter
-	const [cw, cwErr] = $.str.optional().nullable().pipe(isValidCw).get(params.cw);
-	if (cwErr) return rej('invalid cw');
-
-	// Get 'viaMobile' parameter
-	const [viaMobile = false, viaMobileErr] = $.bool.optional().get(params.viaMobile);
-	if (viaMobileErr) return rej('invalid viaMobile');
-
-	// Get 'tags' parameter
-	const [tags = [], tagsErr] = $.arr($.str.range(1, 32)).optional().unique().get(params.tags);
-	if (tagsErr) return rej('invalid tags');
-
-	// Get 'geo' parameter
-	const [geo, geoErr] = $.obj.optional().nullable().strict()
-		.have('coordinates', $.arr().length(2)
-			.item(0, $.num.range(-180, 180))
-			.item(1, $.num.range(-90, 90)))
-		.have('altitude', $.num.nullable())
-		.have('accuracy', $.num.nullable())
-		.have('altitudeAccuracy', $.num.nullable())
-		.have('heading', $.num.nullable().range(0, 360))
-		.have('speed', $.num.nullable())
-		.get(params.geo);
-	if (geoErr) return rej('invalid geo');
-
-	// Get 'mediaIds' parameter
-	const [mediaIds, mediaIdsErr] = $.arr($.type(ID)).optional().unique().range(1, 4).get(params.mediaIds);
-	if (mediaIdsErr) return rej('invalid mediaIds');
-
-	let files = [];
-	if (mediaIds !== undefined) {
+	let files: IDriveFile[] = [];
+	if (ps.mediaIds !== undefined) {
 		// Fetch files
 		// forEach だと途中でエラーなどがあっても return できないので
 		// 敢えて for を使っています。
-		for (const mediaId of mediaIds) {
+		for (const mediaId of ps.mediaIds) {
 			// Fetch file
 			// SELECT _id
 			const entity = await DriveFile.findOne({
@@ -101,15 +118,11 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		files = null;
 	}
 
-	// Get 'renoteId' parameter
-	const [renoteId, renoteIdErr] = $.type(ID).optional().get(params.renoteId);
-	if (renoteIdErr) return rej('invalid renoteId');
-
 	let renote: INote = null;
-	if (renoteId !== undefined) {
+	if (ps.renoteId !== undefined) {
 		// Fetch renote to note
 		renote = await Note.findOne({
-			_id: renoteId
+			_id: ps.renoteId
 		});
 
 		if (renote == null) {
@@ -120,7 +133,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	}
 
 	// Get 'replyId' parameter
-	const [replyId, replyIdErr] = $.type(ID).optional().get(params.replyId);
+	const [replyId, replyIdErr] = $.type(ID).optional.get(params.replyId);
 	if (replyIdErr) return rej('invalid replyId');
 
 	let reply: INote = null;
@@ -140,17 +153,8 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 		}
 	}
 
-	// Get 'poll' parameter
-	const [poll, pollErr] = $.obj.optional().strict()
-		.have('choices', $.arr($.str)
-			.unique()
-			.range(2, 10)
-			.each(c => c.length > 0 && c.length < 50))
-		.get(params.poll);
-	if (pollErr) return rej('invalid poll');
-
-	if (poll) {
-		(poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({
+	if (ps.poll) {
+		(ps.poll as any).choices = (ps.poll as any).choices.map((choice: string, i: number) => ({
 			id: i, // IDを付与
 			text: choice.trim(),
 			votes: 0
@@ -158,7 +162,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	}
 
 	// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
-	if ((text === undefined || text === null) && files === null && renote === null && poll === undefined) {
+	if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) {
 		return rej('text, mediaIds, renoteId or poll is required');
 	}
 
@@ -166,17 +170,16 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async
 	const note = await create(user, {
 		createdAt: new Date(),
 		media: files,
-		poll,
-		text,
+		poll: ps.poll,
+		text: ps.text,
 		reply,
 		renote,
-		cw,
-		tags,
+		cw: ps.cw,
 		app,
-		viaMobile,
-		visibility,
+		viaMobile: ps.viaMobile,
+		visibility: ps.visibility,
 		visibleUsers,
-		geo
+		geo: ps.geo
 	});
 
 	const noteObj = await pack(note, user);
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 24ffdbcba7..d032aa1a62 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -9,23 +9,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// ミュートしているユーザーを取得
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 48490638d2..74462ce4e4 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -9,23 +9,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// ミュートしているユーザーを取得
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 45511603af..06ddc258b0 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -10,19 +10,19 @@ import { ILocalUser } from '../../../../models/user';
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
-		$.bool.optional().get(params.following);
+		$.bool.optional.get(params.following);
 	if (followingError) return rej('invalid following param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index 640140c3d1..fb1ee6dda8 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -8,11 +8,11 @@ import { ILocalUser } from '../../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get votes
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index d3b2d43432..cf88f3860a 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -12,15 +12,15 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort);
+	const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 4aaf1d322b..3b209b3176 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Lookup note
diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts
index ea3f174e1a..043a653e83 100644
--- a/src/server/api/endpoints/notes/reposts.ts
+++ b/src/server/api/endpoints/notes/reposts.ts
@@ -11,15 +11,15 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej)
 	if (noteIdErr) return rej('invalid noteId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 20c628b84d..3dbf407dff 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -11,11 +11,11 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	es.search({
diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts
index 9be7cfffb6..78487e2c03 100644
--- a/src/server/api/endpoints/notes/search_by_tag.ts
+++ b/src/server/api/endpoints/notes/search_by_tag.ts
@@ -14,59 +14,59 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (tagError) return rej('invalid tag param');
 
 	// Get 'includeUserIds' parameter
-	const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional().get(params.includeUserIds);
+	const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional.get(params.includeUserIds);
 	if (includeUserIdsErr) return rej('invalid includeUserIds param');
 
 	// Get 'excludeUserIds' parameter
-	const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional().get(params.excludeUserIds);
+	const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional.get(params.excludeUserIds);
 	if (excludeUserIdsErr) return rej('invalid excludeUserIds param');
 
 	// Get 'includeUserUsernames' parameter
-	const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional().get(params.includeUserUsernames);
+	const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional.get(params.includeUserUsernames);
 	if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param');
 
 	// Get 'excludeUserUsernames' parameter
-	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional().get(params.excludeUserUsernames);
+	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional.get(params.excludeUserUsernames);
 	if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param');
 
 	// Get 'following' parameter
-	const [following = null, followingErr] = $.bool.optional().nullable().get(params.following);
+	const [following = null, followingErr] = $.bool.optional.nullable.get(params.following);
 	if (followingErr) return rej('invalid following param');
 
 	// Get 'mute' parameter
-	const [mute = 'mute_all', muteErr] = $.str.optional().get(params.mute);
+	const [mute = 'mute_all', muteErr] = $.str.optional.get(params.mute);
 	if (muteErr) return rej('invalid mute param');
 
 	// Get 'reply' parameter
-	const [reply = null, replyErr] = $.bool.optional().nullable().get(params.reply);
+	const [reply = null, replyErr] = $.bool.optional.nullable.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote = null, renoteErr] = $.bool.optional().nullable().get(params.renote);
+	const [renote = null, renoteErr] = $.bool.optional.nullable.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media = null, mediaErr] = $.bool.optional().nullable().get(params.media);
+	const [media = null, mediaErr] = $.bool.optional.nullable.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll = null, pollErr] = $.bool.optional().nullable().get(params.poll);
+	const [poll = null, pollErr] = $.bool.optional.nullable.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	if (includeUserUsernames != null) {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index 18c0acd379..9a5306be61 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -10,23 +10,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -35,15 +35,15 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'includeMyRenotes' parameter
-	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes);
+	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
 	if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
 
 	// Get 'includeRenotedMyNotes' parameter
-	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes);
+	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	const [followings, mutedUserIds] = await Promise.all([
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
index 9c0a1bb112..b4acd7c5f4 100644
--- a/src/server/api/endpoints/notes/trend.ts
+++ b/src/server/api/endpoints/notes/trend.ts
@@ -8,27 +8,27 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'reply' parameter
-	const [reply, replyErr] = $.bool.optional().get(params.reply);
+	const [reply, replyErr] = $.bool.optional.get(params.reply);
 	if (replyErr) return rej('invalid reply param');
 
 	// Get 'renote' parameter
-	const [renote, renoteErr] = $.bool.optional().get(params.renote);
+	const [renote, renoteErr] = $.bool.optional.get(params.renote);
 	if (renoteErr) return rej('invalid renote param');
 
 	// Get 'media' parameter
-	const [media, mediaErr] = $.bool.optional().get(params.media);
+	const [media, mediaErr] = $.bool.optional.get(params.media);
 	if (mediaErr) return rej('invalid media param');
 
 	// Get 'poll' parameter
-	const [poll, pollErr] = $.bool.optional().get(params.poll);
+	const [poll, pollErr] = $.bool.optional.get(params.poll);
 	if (pollErr) return rej('invalid poll param');
 
 	const query = {
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index 8aa800b712..f14a869c7f 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -10,23 +10,23 @@ import { ILocalUser } from '../../../../models/user';
  */
 module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) throw 'invalid sinceId param';
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) throw 'invalid untilId param';
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
@@ -35,15 +35,15 @@ module.exports = async (params: any, user: ILocalUser) => {
 	}
 
 	// Get 'includeMyRenotes' parameter
-	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes);
+	const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
 	if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
 
 	// Get 'includeRenotedMyNotes' parameter
-	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes);
+	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
 
 	// Get 'mediaOnly' parameter
-	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly);
+	const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
 	if (mediaOnlyErr) throw 'invalid mediaOnly param';
 
 	// Get 'listId' parameter
diff --git a/src/server/api/endpoints/reversi/games.ts b/src/server/api/endpoints/reversi/games.ts
index 1455f191f7..e68f57c6d4 100644
--- a/src/server/api/endpoints/reversi/games.ts
+++ b/src/server/api/endpoints/reversi/games.ts
@@ -4,19 +4,19 @@ import { ILocalUser } from '../../../../models/user';
 
 module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'my' parameter
-	const [my = false, myErr] = $.bool.optional().get(params.my);
+	const [my = false, myErr] = $.bool.optional.get(params.my);
 	if (myErr) return rej('invalid my param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Check if both of sinceId and untilId is specified
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index b8df6f3ecf..0756ddc918 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -6,15 +6,15 @@ import User, { pack, ILocalUser } from '../../../models/user';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'sort' parameter
-	const [sort, sortError] = $.str.optional().or('+follower|-follower').get(params.sort);
+	const [sort, sortError] = $.str.optional.or('+follower|-follower').get(params.sort);
 	if (sortError) return rej('invalid sort param');
 
 	// Construct query
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 53133ee969..ef36a0df46 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -13,15 +13,15 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 2061200198..2c38fe4f87 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -13,15 +13,15 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
-	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
+	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'cursor' parameter
-	const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor);
+	const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
 	if (cursorErr) return rej('invalid cursor param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/get_frequently_replied_users.ts b/src/server/api/endpoints/users/get_frequently_replied_users.ts
index ba8779d334..6077420908 100644
--- a/src/server/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts
@@ -8,7 +8,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Lookup user
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 222a8d950a..ac4e17946a 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -8,11 +8,11 @@ import User, { ILocalUser } from '../../../../models/user';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).optional().get(params.userId);
+	const [userId, userIdErr] = $.type(ID).optional.get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter
-	const [username, usernameErr] = $.str.optional().get(params.username);
+	const [username, usernameErr] = $.str.optional.get(params.username);
 	if (usernameErr) return rej('invalid username param');
 
 	if (userId === undefined && username === undefined) {
@@ -20,7 +20,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	}
 
 	// Get 'host' parameter
-	const [host, hostErr] = $.str.optional().get(params.host);
+	const [host, hostErr] = $.str.optional.get(params.host);
 	if (hostErr) return rej('invalid host param');
 
 	if (userId === undefined && host === undefined) {
@@ -28,31 +28,31 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	}
 
 	// Get 'includeReplies' parameter
-	const [includeReplies = true, includeRepliesErr] = $.bool.optional().get(params.includeReplies);
+	const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
 	if (includeRepliesErr) return rej('invalid includeReplies param');
 
 	// Get 'withMedia' parameter
-	const [withMedia = false, withMediaErr] = $.bool.optional().get(params.withMedia);
+	const [withMedia = false, withMediaErr] = $.bool.optional.get(params.withMedia);
 	if (withMediaErr) return rej('invalid withMedia param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'sinceId' parameter
-	const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId);
+	const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
 	if (sinceIdErr) return rej('invalid sinceId param');
 
 	// Get 'untilId' parameter
-	const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId);
+	const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
 	if (untilIdErr) return rej('invalid untilId param');
 
 	// Get 'sinceDate' parameter
-	const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate);
+	const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
 	if (sinceDateErr) throw 'invalid sinceDate param';
 
 	// Get 'untilDate' parameter
-	const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate);
+	const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
 	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 1d0d889f11..6221d751b4 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -9,11 +9,11 @@ import Mute from '../../../../models/mute';
  */
 module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// ID list of the user itself and other users who the user follows
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index e29c8d32f1..36a708d21e 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -11,7 +11,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'max' parameter
-	const [max = 10, maxErr] = $.num.optional().range(1, 30).get(params.max);
+	const [max = 10, maxErr] = $.num.optional.range(1, 30).get(params.max);
 	if (maxErr) return rej('invalid max param');
 
 	const escapedQuery = escapeRegexp(query);
diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts
index 937f9af589..1c0f09449c 100644
--- a/src/server/api/endpoints/users/search_by_username.ts
+++ b/src/server/api/endpoints/users/search_by_username.ts
@@ -10,11 +10,11 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	if (queryError) return rej('invalid query param');
 
 	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
+	const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
 	if (offsetErr) return rej('invalid offset param');
 
 	// Get 'limit' parameter
-	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
+	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
 	let users = await User
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index bf7e2a2312..5cbd83f649 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -11,19 +11,19 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) =
 	let user;
 
 	// Get 'userId' parameter
-	const [userId, userIdErr] = $.type(ID).optional().get(params.userId);
+	const [userId, userIdErr] = $.type(ID).optional.get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'userIds' parameter
-	const [userIds, userIdsErr] = $.arr($.type(ID)).optional().get(params.userIds);
+	const [userIds, userIdsErr] = $.arr($.type(ID)).optional.get(params.userIds);
 	if (userIdsErr) return rej('invalid userIds param');
 
 	// Get 'username' parameter
-	const [username, usernameErr] = $.str.optional().get(params.username);
+	const [username, usernameErr] = $.str.optional.get(params.username);
 	if (usernameErr) return rej('invalid username param');
 
 	// Get 'host' parameter
-	const [host, hostErr] = $.str.optional().nullable().get(params.host);
+	const [host, hostErr] = $.str.optional.nullable.get(params.host);
 	if (hostErr) return rej('invalid host param');
 
 	if (userIds) {
diff --git a/src/server/api/get-params.ts b/src/server/api/get-params.ts
index 6b047a28f4..e495e3ef3e 100644
--- a/src/server/api/get-params.ts
+++ b/src/server/api/get-params.ts
@@ -1,25 +1,22 @@
-import { Query } from 'cafy';
+import { Context } from 'cafy';
 
 type Defs = {
-	params: {[key: string]: {
-		def: Query<any>;
-		default?: any;
-	}}
+	params: { [key: string]: Context<any> }
 };
 
 export default function <T extends Defs>(defs: T, params: any): [{
-	[P in keyof T['params']]: ReturnType<T['params'][P]['def']['get']>[0];
+	[P in keyof T['params']]: ReturnType<T['params'][P]['get']>[0];
 }, Error] {
 	const x: any = {};
 	let err: Error = null;
 	Object.keys(defs.params).some(k => {
-		const [v, e] = defs.params[k].def.get(params[k]);
+		const [v, e] = defs.params[k].get(params[k]);
 		if (e) {
 			err = e;
 			return true;
 		} else {
-			if (v === undefined && defs.params[k].default) {
-				x[k] = defs.params[k].default;
+			if (v === undefined && defs.params[k].data.default) {
+				x[k] = defs.params[k].data.default;
 			} else {
 				x[k] = v;
 			}