From 80e5645a84cc60d76f79c48a3d565fb66ad88643 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 18 Jun 2018 09:54:53 +0900
Subject: [PATCH] wip

---
 locales/index.ts                              |   5 +-
 src/acct/parse.ts                             |   2 +-
 src/acct/render.ts                            |   4 +-
 src/build/i18n.ts                             |   4 +-
 src/cafy-id.ts                                |   4 +-
 src/daemons/hashtags-stats-child.ts           |  60 ---
 src/daemons/hashtags-stats.ts                 |  20 -
 src/daemons/notes-stats.ts                    |   2 +-
 src/daemons/server-stats.ts                   |   4 +-
 src/db/mongodb.ts                             |   2 +-
 src/index.ts                                  |   4 +-
 src/models/app.ts                             |   2 +-
 src/models/auth-session.ts                    |   2 +-
 src/models/drive-file.ts                      |   2 +-
 src/models/drive-folder.ts                    |   2 +-
 src/models/favorite.ts                        |   2 +-
 src/models/follow-request.ts                  |   2 +-
 src/models/messaging-message.ts               |   2 +-
 src/models/note-reaction.ts                   |   2 +-
 src/models/note.ts                            |  10 +-
 src/models/notification.ts                    |   2 +-
 src/models/reversi-game.ts                    |   2 +-
 src/models/reversi-matching.ts                |   2 +-
 src/models/signin.ts                          |   2 +-
 src/models/user-list.ts                       |   2 +-
 src/models/user.ts                            |  10 +-
 .../renderer/ordered-collection.ts            |   2 +-
 src/remote/activitypub/renderer/reject.ts     |   2 +-
 src/remote/activitypub/request.ts             |   4 +-
 src/remote/webfinger.ts                       |   4 +-
 src/reversi/ai/back.ts                        | 377 ---------------
 src/reversi/ai/front.ts                       | 233 ----------
 src/reversi/ai/index.ts                       |   1 -
 src/reversi/core.ts                           |   4 +-
 src/server/api/bot/core.ts                    | 439 ------------------
 src/server/api/bot/interfaces/line.ts         | 238 ----------
 src/server/api/common/get-host-lower.ts       |   2 +-
 src/server/api/endpoints/aggregation/posts.ts |   5 +-
 src/server/api/endpoints/aggregation/users.ts |   5 +-
 .../endpoints/aggregation/users/activity.ts   |  15 +-
 .../endpoints/aggregation/users/followers.ts  |   2 +-
 .../endpoints/aggregation/users/following.ts  |   2 +-
 .../api/endpoints/aggregation/users/post.ts   |  15 +-
 .../endpoints/aggregation/users/reaction.ts   |  12 +-
 src/server/api/endpoints/app/create.ts        |  10 +-
 .../api/endpoints/app/name_id/available.ts    |   2 +-
 src/server/api/endpoints/app/show.ts          |   8 +-
 src/server/api/endpoints/auth/accept.ts       |  10 +-
 .../api/endpoints/auth/session/generate.ts    |   2 +-
 src/server/api/endpoints/auth/session/show.ts |  10 +-
 .../api/endpoints/auth/session/userkey.ts     |   2 +-
 src/server/api/endpoints/drive.ts             |   3 +-
 src/server/api/endpoints/drive/files.ts       |   6 +-
 .../api/endpoints/drive/files/create.ts       |   6 +-
 .../api/endpoints/drive/files/delete.ts       |   3 +-
 src/server/api/endpoints/drive/files/find.ts  |   6 +-
 src/server/api/endpoints/drive/files/show.ts  |   6 +-
 .../api/endpoints/drive/files/update.ts       |   6 +-
 src/server/api/endpoints/drive/folders.ts     |   2 +-
 .../api/endpoints/drive/folders/create.ts     |   6 +-
 .../api/endpoints/drive/folders/find.ts       |   6 +-
 .../api/endpoints/drive/folders/show.ts       |   6 +-
 .../api/endpoints/drive/folders/update.ts     |   8 +-
 src/server/api/endpoints/drive/stream.ts      |   6 +-
 src/server/api/endpoints/following/create.ts  |   7 +-
 src/server/api/endpoints/following/delete.ts  |   7 +-
 .../endpoints/following/requests/accept.ts    |   4 +-
 .../endpoints/following/requests/cancel.ts    |   4 +-
 .../api/endpoints/following/requests/list.ts  |   3 +-
 .../endpoints/following/requests/reject.ts    |   4 +-
 src/server/api/endpoints/following/stalk.ts   |   3 +-
 src/server/api/endpoints/following/unstalk.ts |   3 +-
 src/server/api/endpoints/hashtags/trend.ts    |   5 +-
 src/server/api/endpoints/i.ts                 |   8 +-
 src/server/api/endpoints/i/2fa/done.ts        |   7 +-
 src/server/api/endpoints/i/2fa/register.ts    |   7 +-
 src/server/api/endpoints/i/2fa/unregister.ts  |   7 +-
 src/server/api/endpoints/i/authorized_apps.ts |   6 +-
 src/server/api/endpoints/i/change_password.ts |   7 +-
 src/server/api/endpoints/i/favorites.ts       |   6 +-
 src/server/api/endpoints/i/notifications.ts   |   6 +-
 src/server/api/endpoints/i/pin.ts             |   7 +-
 .../api/endpoints/i/regenerate_token.ts       |   7 +-
 src/server/api/endpoints/i/signin_history.ts  |   6 +-
 src/server/api/endpoints/i/update.ts          |   8 +-
 .../api/endpoints/i/update_client_setting.ts  |   9 +-
 src/server/api/endpoints/i/update_home.ts     |   4 +-
 .../api/endpoints/i/update_mobile_home.ts     |   4 +-
 src/server/api/endpoints/i/update_widget.ts   |  12 +-
 src/server/api/endpoints/messaging/history.ts |   6 +-
 .../api/endpoints/messaging/messages.ts       |   4 +-
 .../endpoints/messaging/messages/create.ts    |   7 +-
 src/server/api/endpoints/meta.ts              |   2 +-
 src/server/api/endpoints/mute/create.ts       |   7 +-
 src/server/api/endpoints/mute/delete.ts       |   7 +-
 src/server/api/endpoints/mute/list.ts         |   7 +-
 src/server/api/endpoints/my/apps.ts           |   6 +-
 src/server/api/endpoints/notes.ts             |   2 +-
 .../api/endpoints/notes/conversation.ts       |  12 +-
 src/server/api/endpoints/notes/create.ts      |  11 +-
 src/server/api/endpoints/notes/delete.ts      |   3 +-
 .../api/endpoints/notes/favorites/create.ts   |   6 +-
 .../api/endpoints/notes/favorites/delete.ts   |   6 +-
 .../api/endpoints/notes/global-timeline.ts    |   6 +-
 .../api/endpoints/notes/local-timeline.ts     |   6 +-
 src/server/api/endpoints/notes/mentions.ts    |  10 +-
 .../endpoints/notes/polls/recommendation.ts   |   6 +-
 src/server/api/endpoints/notes/polls/vote.ts  |  19 +-
 src/server/api/endpoints/notes/reactions.ts   |  10 +-
 .../api/endpoints/notes/reactions/create.ts   |   6 +-
 .../api/endpoints/notes/reactions/delete.ts   |   8 +-
 src/server/api/endpoints/notes/replies.ts     |   3 +-
 src/server/api/endpoints/notes/reposts.ts     |  10 +-
 src/server/api/endpoints/notes/search.ts      | 364 ---------------
 .../api/endpoints/notes/search_by_tag.ts      |  26 +-
 src/server/api/endpoints/notes/show.ts        |  10 +-
 src/server/api/endpoints/notes/timeline.ts    |   6 +-
 src/server/api/endpoints/notes/trend.ts       |  10 +-
 .../api/endpoints/notes/user-list-timeline.ts |   6 +-
 .../notifications/mark_as_read_all.ts         |   4 +-
 src/server/api/endpoints/reversi/games.ts     |   3 +-
 .../api/endpoints/reversi/games/show.ts       |   3 +-
 .../api/endpoints/reversi/invitations.ts      |   3 +-
 src/server/api/endpoints/reversi/match.ts     |   4 +-
 .../api/endpoints/reversi/match/cancel.ts     |   3 +-
 src/server/api/endpoints/sw/register.ts       |   6 +-
 .../api/endpoints/username/available.ts       |   8 +-
 src/server/api/endpoints/users.ts             |   7 +-
 src/server/api/endpoints/users/followers.ts   |   7 +-
 src/server/api/endpoints/users/following.ts   |  11 +-
 .../users/get_frequently_replied_users.ts     |   9 +-
 .../api/endpoints/users/lists/create.ts       |   6 +-
 src/server/api/endpoints/users/lists/list.ts  |   3 +-
 src/server/api/endpoints/users/lists/push.ts  |   4 +-
 src/server/api/endpoints/users/lists/show.ts  |   3 +-
 src/server/api/endpoints/users/notes.ts       |   7 +-
 .../api/endpoints/users/recommendation.ts     |  11 +-
 src/server/api/endpoints/users/search.ts      |  73 +--
 .../api/endpoints/users/search_by_username.ts |   7 +-
 src/server/api/endpoints/users/show.ts        |   9 +-
 src/server/api/private/signup.ts              |   2 +-
 src/server/api/service/github.ts              |   4 +-
 src/server/api/stream/notes-stats.ts          |   2 +-
 src/server/api/stream/requests.ts             |  19 -
 src/server/api/stream/reversi-game.ts         |  14 +-
 src/server/api/stream/server-stats.ts         |   2 +-
 src/server/api/streaming.ts                   |   6 -
 src/server/index.ts                           |   2 +-
 webpack.config.ts                             |  19 +-
 webpack/i18n.ts                               |   2 +-
 150 files changed, 305 insertions(+), 2334 deletions(-)
 delete mode 100644 src/daemons/hashtags-stats-child.ts
 delete mode 100644 src/daemons/hashtags-stats.ts
 delete mode 100644 src/reversi/ai/back.ts
 delete mode 100644 src/reversi/ai/front.ts
 delete mode 100644 src/reversi/ai/index.ts
 delete mode 100644 src/server/api/bot/core.ts
 delete mode 100644 src/server/api/bot/interfaces/line.ts
 delete mode 100644 src/server/api/endpoints/notes/search.ts
 delete mode 100644 src/server/api/stream/requests.ts

diff --git a/locales/index.ts b/locales/index.ts
index 3b4f76b06..2ae84f30a 100644
--- a/locales/index.ts
+++ b/locales/index.ts
@@ -6,15 +6,14 @@ import * as fs from 'fs';
 import * as yaml from 'js-yaml';
 
 export type LangKey = 'de' | 'en' | 'fr' | 'ja' | 'pl';
-export type LocaleObjectChildren = LocaleObject | string | undefined;
-export type LocaleObject = {[key: string]: LocaleObjectChildren };
+export type LocaleObject = { [key: string]: any };
 
 const loadLang = (lang: LangKey) => yaml.safeLoad(
 	fs.readFileSync(`./locales/${lang}.yml`, 'utf-8')) as LocaleObject;
 
 const native = loadLang('ja');
 
-const langs: {[key in LangKey]: LocaleObject} = {
+const langs: { [key: string]: LocaleObject } = {
 	'de': loadLang('de'),
 	'en': loadLang('en'),
 	'fr': loadLang('fr'),
diff --git a/src/acct/parse.ts b/src/acct/parse.ts
index ef1f55405..0c00fccef 100644
--- a/src/acct/parse.ts
+++ b/src/acct/parse.ts
@@ -1,4 +1,4 @@
-export default acct => {
+export default (acct: string) => {
 	const splitted = acct.split('@', 2);
 	return { username: splitted[0], host: splitted[1] || null };
 };
diff --git a/src/acct/render.ts b/src/acct/render.ts
index 9afb03d88..191034361 100644
--- a/src/acct/render.ts
+++ b/src/acct/render.ts
@@ -1,3 +1,5 @@
-export default user => {
+import { IUser } from "../models/user";
+
+export default (user: IUser) => {
 	return user.host === null ? user.username : `${user.username}@${user.host}`;
 };
diff --git a/src/build/i18n.ts b/src/build/i18n.ts
index 308ff0da0..f7602dfd1 100644
--- a/src/build/i18n.ts
+++ b/src/build/i18n.ts
@@ -2,7 +2,7 @@
  * Replace i18n texts
  */
 
-import locale, { isAvailableLanguage, LocaleObject, LocaleObjectChildren } from '../../locales';
+import locale, { isAvailableLanguage, LocaleObject } from '../../locales';
 
 export default class Replacer {
 	private lang: string;
@@ -24,7 +24,7 @@ export default class Replacer {
 
 		const texts = locale[this.lang];
 
-		let text: LocaleObjectChildren = texts;
+		let text = texts;
 
 		if (path) {
 			if (text.hasOwnProperty(path)) {
diff --git a/src/cafy-id.ts b/src/cafy-id.ts
index 310b1eb20..dac0f97bd 100644
--- a/src/cafy-id.ts
+++ b/src/cafy-id.ts
@@ -1,8 +1,8 @@
 import * as mongo from 'mongodb';
 import { Query } from 'cafy';
 
-export const isAnId = x => mongo.ObjectID.isValid(x);
-export const isNotAnId = x => !isAnId(x);
+export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
+export const isNotAnId = (x: any) => !isAnId(x);
 
 /**
  * ID
diff --git a/src/daemons/hashtags-stats-child.ts b/src/daemons/hashtags-stats-child.ts
deleted file mode 100644
index 3f7f4d6e9..000000000
--- a/src/daemons/hashtags-stats-child.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import Note from '../models/note';
-
-// 10分
-const interval = 1000 * 60 * 10;
-
-async function tick() {
-	const res = await Note.aggregate([{
-		$match: {
-			createdAt: {
-				$gt: new Date(Date.now() - interval)
-			},
-			tags: {
-				$exists: true,
-				$ne: []
-			}
-		}
-	}, {
-		$unwind: '$tags'
-	}, {
-		$group: {
-			_id: '$tags',
-			count: {
-				$sum: 1
-			}
-		}
-	}, {
-		$group: {
-			_id: null,
-			tags: {
-				$push: {
-					tag: '$_id',
-					count: '$count'
-				}
-			}
-		}
-	}, {
-		$project: {
-			_id: false,
-			tags: true
-		}
-	}]) as {
-		tags: Array<{
-			tag: string;
-			count: number;
-		}>
-	};
-
-	const stats = res.tags
-		.sort((a, b) => a.count - b.count)
-		.map(tag => [tag.tag, tag.count])
-		.slice(0, 10);
-
-	console.log(stats);
-
-	process.send(stats);
-}
-
-tick();
-
-setInterval(tick, interval);
diff --git a/src/daemons/hashtags-stats.ts b/src/daemons/hashtags-stats.ts
deleted file mode 100644
index 5ed028ac3..000000000
--- a/src/daemons/hashtags-stats.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as childProcess from 'child_process';
-import Xev from 'xev';
-
-const ev = new Xev();
-
-export default function() {
-	const log = [];
-
-	const p = childProcess.fork(__dirname + '/hashtags-stats-child.js');
-
-	p.on('message', stats => {
-		ev.emit('hashtagsStats', stats);
-		log.push(stats);
-		if (log.length > 30) log.shift();
-	});
-
-	ev.on('requestHashTagsStatsLog', id => {
-		ev.emit('hashtagsStatsLog:' + id, log);
-	});
-}
diff --git a/src/daemons/notes-stats.ts b/src/daemons/notes-stats.ts
index 3094c34af..021e6d64a 100644
--- a/src/daemons/notes-stats.ts
+++ b/src/daemons/notes-stats.ts
@@ -4,7 +4,7 @@ import Xev from 'xev';
 const ev = new Xev();
 
 export default function() {
-	const log = [];
+	const log: any[] = [];
 
 	const p = childProcess.fork(__dirname + '/notes-stats-child.js');
 
diff --git a/src/daemons/server-stats.ts b/src/daemons/server-stats.ts
index 140340250..5c793c662 100644
--- a/src/daemons/server-stats.ts
+++ b/src/daemons/server-stats.ts
@@ -11,14 +11,14 @@ const interval = 1000;
  * Report server stats regularly
  */
 export default function() {
-	const log = [];
+	const log: any[] = [];
 
 	ev.on('requestServerStatsLog', id => {
 		ev.emit('serverStatsLog:' + id, log);
 	});
 
 	async function tick() {
-		osUtils.cpuUsage(cpuUsage => {
+		osUtils.cpuUsage((cpuUsage: number) => {
 			const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/');
 			const stats = {
 				cpu_usage: cpuUsage,
diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts
index 05bb72bfd..0df87ea3a 100644
--- a/src/db/mongodb.ts
+++ b/src/db/mongodb.ts
@@ -27,7 +27,7 @@ const nativeDbConn = async (): Promise<mongodb.Db> => {
 	if (mdb) return mdb;
 
 	const db = await ((): Promise<mongodb.Db> => new Promise((resolve, reject) => {
-		(mongodb as any).MongoClient.connect(uri, (e, client) => {
+		(mongodb as any).MongoClient.connect(uri, (e: Error, client: any) => {
 			if (e) return reject(e);
 			resolve(client.db(config.mongodb.db));
 		});
diff --git a/src/index.ts b/src/index.ts
index 35cf5a243..c89252dfc 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -60,7 +60,7 @@ function main() {
 /**
  * Init master process
  */
-async function masterMain(opt) {
+async function masterMain(opt: any) {
 	let config: Config;
 
 	try {
@@ -91,7 +91,7 @@ async function masterMain(opt) {
 /**
  * Init worker process
  */
-async function workerMain(opt) {
+async function workerMain(opt: any) {
 	if (!opt['only-processor']) {
 		// start server
 		await require('./server').default();
diff --git a/src/models/app.ts b/src/models/app.ts
index 7926f2fac..8dc7fe01d 100644
--- a/src/models/app.ts
+++ b/src/models/app.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import AccessToken from './access-token';
 import db from '../db/mongodb';
 import config from '../config';
diff --git a/src/models/auth-session.ts b/src/models/auth-session.ts
index 219b1a4c8..3d2c9ee3c 100644
--- a/src/models/auth-session.ts
+++ b/src/models/auth-session.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { pack as packApp } from './app';
 
diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts
index bb98c11a9..2bdf38f48 100644
--- a/src/models/drive-file.ts
+++ b/src/models/drive-file.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import { pack as packFolder } from './drive-folder';
 import config from '../config';
 import monkDb, { nativeDbConn } from '../db/mongodb';
diff --git a/src/models/drive-folder.ts b/src/models/drive-folder.ts
index cafb9cdf1..def519fad 100644
--- a/src/models/drive-folder.ts
+++ b/src/models/drive-folder.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import DriveFile from './drive-file';
 
diff --git a/src/models/favorite.ts b/src/models/favorite.ts
index 45417212e..b2d2fc93e 100644
--- a/src/models/favorite.ts
+++ b/src/models/favorite.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { pack as packNote } from './note';
 
diff --git a/src/models/follow-request.ts b/src/models/follow-request.ts
index eea5d1c53..fdb20011f 100644
--- a/src/models/follow-request.ts
+++ b/src/models/follow-request.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { pack as packUser } from './user';
 
diff --git a/src/models/messaging-message.ts b/src/models/messaging-message.ts
index ad2d1657e..f46abd506 100644
--- a/src/models/messaging-message.ts
+++ b/src/models/messaging-message.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import { pack as packUser } from './user';
 import { pack as packFile } from './drive-file';
 import db from '../db/mongodb';
diff --git a/src/models/note-reaction.ts b/src/models/note-reaction.ts
index e5e108c01..915dc0cf9 100644
--- a/src/models/note-reaction.ts
+++ b/src/models/note-reaction.ts
@@ -1,6 +1,6 @@
 import * as mongo from 'mongodb';
 import $ from 'cafy';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import Reaction from './note-reaction';
 import { pack as packUser } from './user';
diff --git a/src/models/note.ts b/src/models/note.ts
index 83e85f849..83cd93353 100644
--- a/src/models/note.ts
+++ b/src/models/note.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import rap from '@prezzemolo/rap';
 import db from '../db/mongodb';
 import { IUser, pack as packUser } from './user';
@@ -37,7 +37,11 @@ export type INote = {
 	mediaIds: mongo.ObjectID[];
 	replyId: mongo.ObjectID;
 	renoteId: mongo.ObjectID;
-	poll: any; // todo
+	poll: {
+		choices: Array<{
+			id: number;
+		}>
+	};
 	text: string;
 	tags: string[];
 	tagsLower: string[];
@@ -304,7 +308,7 @@ export const pack = async (
 
 				if (vote != null) {
 					const myChoice = poll.choices
-						.filter(c => c.id == vote.choice)[0];
+						.filter((c: any) => c.id == vote.choice)[0];
 
 					myChoice.isVoted = true;
 				}
diff --git a/src/models/notification.ts b/src/models/notification.ts
index 875c6952b..097e3e691 100644
--- a/src/models/notification.ts
+++ b/src/models/notification.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { IUser, pack as packUser } from './user';
 import { pack as packNote } from './note';
diff --git a/src/models/reversi-game.ts b/src/models/reversi-game.ts
index 16b9ab0d4..cf497f056 100644
--- a/src/models/reversi-game.ts
+++ b/src/models/reversi-game.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { IUser, pack as packUser } from './user';
 
diff --git a/src/models/reversi-matching.ts b/src/models/reversi-matching.ts
index 5efa5d76a..90227bd12 100644
--- a/src/models/reversi-matching.ts
+++ b/src/models/reversi-matching.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 import { IUser, pack as packUser } from './user';
 
diff --git a/src/models/signin.ts b/src/models/signin.ts
index d8b05c0e3..55485d866 100644
--- a/src/models/signin.ts
+++ b/src/models/signin.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 
 const Signin = db.get<ISignin>('signin');
diff --git a/src/models/user-list.ts b/src/models/user-list.ts
index 4cf1de61a..5cfa7e4df 100644
--- a/src/models/user-list.ts
+++ b/src/models/user-list.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import db from '../db/mongodb';
 
 const UserList = db.get<IUserList>('userList');
diff --git a/src/models/user.ts b/src/models/user.ts
index f0620a6cf..942faeeff 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -1,5 +1,5 @@
 import * as mongo from 'mongodb';
-import * as deepcopy from 'deepcopy';
+const deepcopy = require('deepcopy');
 import sequential = require('promise-sequential');
 import rap from '@prezzemolo/rap';
 import db from '../db/mongodb';
@@ -153,14 +153,6 @@ export function isValidBirthday(birthday: string): boolean {
 }
 //#endregion
 
-export function init(user): IUser {
-	user._id = new mongo.ObjectID(user._id);
-	user.avatarId = new mongo.ObjectID(user.avatarId);
-	user.bannerId = new mongo.ObjectID(user.bannerId);
-	user.pinnedNoteId = new mongo.ObjectID(user.pinnedNoteId);
-	return user;
-}
-
 /**
  * Userを物理削除します
  */
diff --git a/src/remote/activitypub/renderer/ordered-collection.ts b/src/remote/activitypub/renderer/ordered-collection.ts
index 2ca0f7735..9d543b1e1 100644
--- a/src/remote/activitypub/renderer/ordered-collection.ts
+++ b/src/remote/activitypub/renderer/ordered-collection.ts
@@ -1,4 +1,4 @@
-export default (id, totalItems, orderedItems) => ({
+export default (id: string, totalItems: any, orderedItems: any) => ({
 	id,
 	type: 'OrderedCollection',
 	totalItems,
diff --git a/src/remote/activitypub/renderer/reject.ts b/src/remote/activitypub/renderer/reject.ts
index 29c998a6b..2464486c2 100644
--- a/src/remote/activitypub/renderer/reject.ts
+++ b/src/remote/activitypub/renderer/reject.ts
@@ -1,4 +1,4 @@
-export default object => ({
+export default (object: any) => ({
 	type: 'Reject',
 	object
 });
diff --git a/src/remote/activitypub/request.ts b/src/remote/activitypub/request.ts
index e6861fdb3..e2b600ae2 100644
--- a/src/remote/activitypub/request.ts
+++ b/src/remote/activitypub/request.ts
@@ -1,5 +1,5 @@
 import { request } from 'https';
-import { sign } from 'http-signature';
+const { sign } = require('http-signature');
 import { URL } from 'url';
 import * as debug from 'debug';
 
@@ -8,7 +8,7 @@ import { ILocalUser } from '../../models/user';
 
 const log = debug('misskey:activitypub:deliver');
 
-export default (user: ILocalUser, url: string, object) => new Promise((resolve, reject) => {
+export default (user: ILocalUser, url: string, object: any) => new Promise((resolve, reject) => {
 	log(`--> ${url}`);
 
 	const { protocol, hostname, port, pathname, search } = new URL(url);
diff --git a/src/remote/webfinger.ts b/src/remote/webfinger.ts
index 4f1ff231c..cba09379a 100644
--- a/src/remote/webfinger.ts
+++ b/src/remote/webfinger.ts
@@ -12,8 +12,8 @@ type IWebFinger = {
 	subject: string;
 };
 
-export default async function resolve(query): Promise<IWebFinger> {
-	return await new Promise((res, rej) => webFinger.lookup(query, (error, result) => {
+export default async function resolve(query: any): Promise<IWebFinger> {
+	return await new Promise((res, rej) => webFinger.lookup(query, (error: Error, result: any) => {
 		if (error) {
 			return rej(error);
 		}
diff --git a/src/reversi/ai/back.ts b/src/reversi/ai/back.ts
deleted file mode 100644
index 42f1a0f4b..000000000
--- a/src/reversi/ai/back.ts
+++ /dev/null
@@ -1,377 +0,0 @@
-/**
- * -AI-
- * Botのバックエンド(思考を担当)
- *
- * 対話と思考を同じプロセスで行うと、思考時間が長引いたときにストリームから
- * 切断されてしまうので、別々のプロセスで行うようにします
- */
-
-import * as request from 'request-promise-native';
-import Reversi, { Color } from '../core';
-import conf from '../../config';
-import getUserName from '../../renderers/get-user-name';
-
-let game;
-let form;
-
-/**
- * BotアカウントのユーザーID
- */
-const id = conf.reversi_ai.id;
-
-/**
- * BotアカウントのAPIキー
- */
-const i = conf.reversi_ai.i;
-
-let note;
-
-process.on('message', async msg => {
-	// 親プロセスからデータをもらう
-	if (msg.type == '_init_') {
-		game = msg.game;
-		form = msg.form;
-	}
-
-	// フォームが更新されたとき
-	if (msg.type == 'update-form') {
-		form.find(i => i.id == msg.body.id).value = msg.body.value;
-	}
-
-	// ゲームが始まったとき
-	if (msg.type == 'started') {
-		onGameStarted(msg.body);
-
-		//#region TLに投稿する
-		const game = msg.body;
-		const url = `${conf.url}/reversi/${game.id}`;
-		const user = game.user1Id == id ? game.user2 : game.user1;
-		const isSettai = form[0].value === 0;
-		const text = isSettai
-			? `?[${getUserName(user)}](${conf.url}/@${user.username})さんの接待を始めました!`
-			: `対局を?[${getUserName(user)}](${conf.url}/@${user.username})さんと始めました! (強さ${form[0].value})`;
-
-		const res = await request.post(`${conf.api_url}/notes/create`, {
-			json: { i,
-				text: `${text}\n→[観戦する](${url})`
-			}
-		});
-
-		note = res.createdNote;
-		//#endregion
-	}
-
-	// ゲームが終了したとき
-	if (msg.type == 'ended') {
-		// ストリームから切断
-		process.send({
-			type: 'close'
-		});
-
-		//#region TLに投稿する
-		const user = game.user1Id == id ? game.user2 : game.user1;
-		const isSettai = form[0].value === 0;
-		const text = isSettai
-			? msg.body.winnerId === null
-				? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で引き分けました...`
-				: msg.body.winnerId == id
-					? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で勝ってしまいました...`
-					: `?[${getUserName(user)}](${conf.url}/@${user.username})さんに接待で負けてあげました♪`
-			: msg.body.winnerId === null
-				? `?[${getUserName(user)}](${conf.url}/@${user.username})さんと引き分けました~`
-				: msg.body.winnerId == id
-					? `?[${getUserName(user)}](${conf.url}/@${user.username})さんに勝ちました♪`
-					: `?[${getUserName(user)}](${conf.url}/@${user.username})さんに負けました...`;
-
-		await request.post(`${conf.api_url}/notes/create`, {
-			json: { i,
-				renoteId: note.id,
-				text: text
-			}
-		});
-		//#endregion
-
-		process.exit();
-	}
-
-	// 打たれたとき
-	if (msg.type == 'set') {
-		onSet(msg.body);
-	}
-});
-
-let o: Reversi;
-let botColor: Color;
-
-// 各マスの強さ
-let cellWeights;
-
-/**
- * ゲーム開始時
- * @param g ゲーム情報
- */
-function onGameStarted(g) {
-	game = g;
-
-	// リバーシエンジン初期化
-	o = new Reversi(game.settings.map, {
-		isLlotheo: game.settings.isLlotheo,
-		canPutEverywhere: game.settings.canPutEverywhere,
-		loopedBoard: game.settings.loopedBoard
-	});
-
-	// 各マスの価値を計算しておく
-	cellWeights = o.map.map((pix, i) => {
-		if (pix == 'null') return 0;
-		const [x, y] = o.transformPosToXy(i);
-		let count = 0;
-		const get = (x, y) => {
-			if (x < 0 || y < 0 || x >= o.mapWidth || y >= o.mapHeight) return 'null';
-			return o.mapDataGet(o.transformXyToPos(x, y));
-		};
-
-		if (get(x    , y - 1) == 'null') count++;
-		if (get(x + 1, y - 1) == 'null') count++;
-		if (get(x + 1, y    ) == 'null') count++;
-		if (get(x + 1, y + 1) == 'null') count++;
-		if (get(x    , y + 1) == 'null') count++;
-		if (get(x - 1, y + 1) == 'null') count++;
-		if (get(x - 1, y    ) == 'null') count++;
-		if (get(x - 1, y - 1) == 'null') count++;
-		//return Math.pow(count, 3);
-		return count >= 4 ? 1 : 0;
-	});
-
-	botColor = game.user1Id == id && game.black == 1 || game.user2Id == id && game.black == 2;
-
-	if (botColor) {
-		think();
-	}
-}
-
-function onSet(x) {
-	o.put(x.color, x.pos);
-
-	if (x.next === botColor) {
-		think();
-	}
-}
-
-const db = {};
-
-function think() {
-	console.log('Thinking...');
-	console.time('think');
-
-	const isSettai = form[0].value === 0;
-
-	// 接待モードのときは、全力(5手先読みくらい)で負けるようにする
-	const maxDepth = isSettai ? 5 : form[0].value;
-
-	/**
-	 * Botにとってある局面がどれだけ有利か取得する
-	 */
-	function staticEval() {
-		let score = o.canPutSomewhere(botColor).length;
-
-		cellWeights.forEach((weight, i) => {
-			// 係数
-			const coefficient = 30;
-			weight = weight * coefficient;
-
-			const stone = o.board[i];
-			if (stone === botColor) {
-				// TODO: 価値のあるマスに設置されている自分の石に縦か横に接するマスは価値があると判断する
-				score += weight;
-			} else if (stone !== null) {
-				score -= weight;
-			}
-		});
-
-		// ロセオならスコアを反転
-		if (game.settings.isLlotheo) score = -score;
-
-		// 接待ならスコアを反転
-		if (isSettai) score = -score;
-
-		return score;
-	}
-
-	/**
-	 * αβ法での探索
-	 */
-	const dive = (pos: number, alpha = -Infinity, beta = Infinity, depth = 0): number => {
-		// 試し打ち
-		o.put(o.turn, pos);
-
-		const key = o.board.toString();
-		let cache = db[key];
-		if (cache) {
-			if (alpha >= cache.upper) {
-				o.undo();
-				return cache.upper;
-			}
-			if (beta <= cache.lower) {
-				o.undo();
-				return cache.lower;
-			}
-			alpha = Math.max(alpha, cache.lower);
-			beta = Math.min(beta, cache.upper);
-		} else {
-			cache = {
-				upper: Infinity,
-				lower: -Infinity
-			};
-		}
-
-		const isBotTurn = o.turn === botColor;
-
-		// 勝った
-		if (o.turn === null) {
-			const winner = o.winner;
-
-			// 勝つことによる基本スコア
-			const base = 10000;
-
-			let score;
-
-			if (game.settings.isLlotheo) {
-				// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
-				score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
-			} else {
-				// 勝ちは勝ちでも、より相手の石を少なくした方が美しい勝ちだと判定する
-				score = o.winner ? base + (o.blackCount * 100) : base + (o.whiteCount * 100);
-			}
-
-			// 巻き戻し
-			o.undo();
-
-			// 接待なら自分が負けた方が高スコア
-			return isSettai
-				? winner !== botColor ? score : -score
-				: winner === botColor ? score : -score;
-		}
-
-		if (depth === maxDepth) {
-			// 静的に評価
-			const score = staticEval();
-
-			// 巻き戻し
-			o.undo();
-
-			return score;
-		} else {
-			const cans = o.canPutSomewhere(o.turn);
-
-			let value = isBotTurn ? -Infinity : Infinity;
-			let a = alpha;
-			let b = beta;
-
-			// 次のターンのプレイヤーにとって最も良い手を取得
-			for (const p of cans) {
-				if (isBotTurn) {
-					const score = dive(p, a, beta, depth + 1);
-					value = Math.max(value, score);
-					a = Math.max(a, value);
-					if (value >= beta) break;
-				} else {
-					const score = dive(p, alpha, b, depth + 1);
-					value = Math.min(value, score);
-					b = Math.min(b, value);
-					if (value <= alpha) break;
-				}
-			}
-
-			// 巻き戻し
-			o.undo();
-
-			if (value <= alpha) {
-				cache.upper = value;
-			} else if (value >= beta) {
-				cache.lower = value;
-			} else {
-				cache.upper = value;
-				cache.lower = value;
-			}
-
-			db[key] = cache;
-
-			return value;
-		}
-	};
-
-	/**
-	 * αβ法での探索(キャッシュ無し)(デバッグ用)
-	 */
-	const dive2 = (pos: number, alpha = -Infinity, beta = Infinity, depth = 0): number => {
-		// 試し打ち
-		o.put(o.turn, pos);
-
-		const isBotTurn = o.turn === botColor;
-
-		// 勝った
-		if (o.turn === null) {
-			const winner = o.winner;
-
-			// 勝つことによる基本スコア
-			const base = 10000;
-
-			let score;
-
-			if (game.settings.isLlotheo) {
-				// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
-				score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
-			} else {
-				// 勝ちは勝ちでも、より相手の石を少なくした方が美しい勝ちだと判定する
-				score = o.winner ? base + (o.blackCount * 100) : base + (o.whiteCount * 100);
-			}
-
-			// 巻き戻し
-			o.undo();
-
-			// 接待なら自分が負けた方が高スコア
-			return isSettai
-				? winner !== botColor ? score : -score
-				: winner === botColor ? score : -score;
-		}
-
-		if (depth === maxDepth) {
-			// 静的に評価
-			const score = staticEval();
-
-			// 巻き戻し
-			o.undo();
-
-			return score;
-		} else {
-			const cans = o.canPutSomewhere(o.turn);
-
-			// 次のターンのプレイヤーにとって最も良い手を取得
-			for (const p of cans) {
-				if (isBotTurn) {
-					alpha = Math.max(alpha, dive2(p, alpha, beta, depth + 1));
-				} else {
-					beta = Math.min(beta, dive2(p, alpha, beta, depth + 1));
-				}
-				if (alpha >= beta) break;
-			}
-
-			// 巻き戻し
-			o.undo();
-
-			return isBotTurn ? alpha : beta;
-		}
-	};
-
-	const cans = o.canPutSomewhere(botColor);
-	const scores = cans.map(p => dive(p));
-	const pos = cans[scores.indexOf(Math.max(...scores))];
-
-	console.log('Thinked:', pos);
-	console.timeEnd('think');
-
-	process.send({
-		type: 'put',
-		pos
-	});
-}
diff --git a/src/reversi/ai/front.ts b/src/reversi/ai/front.ts
deleted file mode 100644
index 25ee43225..000000000
--- a/src/reversi/ai/front.ts
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * -AI-
- * Botのフロントエンド(ストリームとの対話を担当)
- *
- * 対話と思考を同じプロセスで行うと、思考時間が長引いたときにストリームから
- * 切断されてしまうので、別々のプロセスで行うようにします
- */
-
-import * as childProcess from 'child_process';
-const WebSocket = require('ws');
-import * as ReconnectingWebSocket from 'reconnecting-websocket';
-import * as request from 'request-promise-native';
-import conf from '../../config';
-
-// 設定 ////////////////////////////////////////////////////////
-
-/**
- * BotアカウントのAPIキー
- */
-const i = conf.reversi_ai.i;
-
-/**
- * BotアカウントのユーザーID
- */
-const id = conf.reversi_ai.id;
-
-////////////////////////////////////////////////////////////////
-
-/**
- * ホームストリーム
- */
-const homeStream = new ReconnectingWebSocket(`${conf.ws_url}/?i=${i}`, undefined, {
-	constructor: WebSocket
-});
-
-homeStream.on('open', () => {
-	console.log('home stream opened');
-});
-
-homeStream.on('close', () => {
-	console.log('home stream closed');
-});
-
-homeStream.on('message', message => {
-	const msg = JSON.parse(message.toString());
-
-	// タイムライン上でなんか言われたまたは返信されたとき
-	if (msg.type == 'mention' || msg.type == 'reply') {
-		const note = msg.body;
-
-		if (note.userId == id) return;
-
-		// リアクションする
-		request.post(`${conf.api_url}/notes/reactions/create`, {
-			json: { i,
-				noteId: note.id,
-				reaction: 'love'
-			}
-		});
-
-		if (note.text) {
-			if (note.text.indexOf('リバーシ') > -1) {
-				request.post(`${conf.api_url}/notes/create`, {
-					json: { i,
-						replyId: note.id,
-						text: '良いですよ~'
-					}
-				});
-
-				invite(note.userId);
-			}
-		}
-	}
-
-	// メッセージでなんか言われたとき
-	if (msg.type == 'messaging_message') {
-		const message = msg.body;
-		if (message.text) {
-			if (message.text.indexOf('リバーシ') > -1) {
-				request.post(`${conf.api_url}/messaging/messages/create`, {
-					json: { i,
-						userId: message.userId,
-						text: '良いですよ~'
-					}
-				});
-
-				invite(message.userId);
-			}
-		}
-	}
-});
-
-// ユーザーを対局に誘う
-function invite(userId) {
-	request.post(`${conf.api_url}/reversi/match`, {
-		json: { i,
-			userId: userId
-		}
-	});
-}
-
-/**
- * リバーシストリーム
- */
-const reversiStream = new ReconnectingWebSocket(`${conf.ws_url}/reversi?i=${i}`, undefined, {
-	constructor: WebSocket
-});
-
-reversiStream.on('open', () => {
-	console.log('reversi stream opened');
-});
-
-reversiStream.on('close', () => {
-	console.log('reversi stream closed');
-});
-
-reversiStream.on('message', message => {
-	const msg = JSON.parse(message.toString());
-
-	// 招待されたとき
-	if (msg.type == 'invited') {
-		onInviteMe(msg.body.parent);
-	}
-
-	// マッチしたとき
-	if (msg.type == 'matched') {
-		gameStart(msg.body);
-	}
-});
-
-/**
- * ゲーム開始
- * @param game ゲーム情報
- */
-function gameStart(game) {
-	// ゲームストリームに接続
-	const gw = new ReconnectingWebSocket(`${conf.ws_url}/reversi-game?i=${i}&game=${game.id}`, undefined, {
-		constructor: WebSocket
-	});
-
-	gw.on('open', () => {
-		console.log('reversi game stream opened');
-
-		// フォーム
-		const form = [{
-			id: 'strength',
-			type: 'radio',
-			label: '強さ',
-			value: 2,
-			items: [{
-				label: '接待',
-				value: 0
-			}, {
-				label: '弱',
-				value: 1
-			}, {
-				label: '中',
-				value: 2
-			}, {
-				label: '強',
-				value: 3
-			}, {
-				label: '最強',
-				value: 5
-			}]
-		}];
-
-		//#region バックエンドプロセス開始
-		const ai = childProcess.fork(__dirname + '/back.js');
-
-		// バックエンドプロセスに情報を渡す
-		ai.send({
-			type: '_init_',
-			game,
-			form
-		});
-
-		ai.on('message', msg => {
-			if (msg.type == 'put') {
-				gw.send(JSON.stringify({
-					type: 'set',
-					pos: msg.pos
-				}));
-			} else if (msg.type == 'close') {
-				gw.close();
-			}
-		});
-
-		// ゲームストリームから情報が流れてきたらそのままバックエンドプロセスに伝える
-		gw.on('message', message => {
-			const msg = JSON.parse(message.toString());
-			ai.send(msg);
-		});
-		//#endregion
-
-		// フォーム初期化
-		setTimeout(() => {
-			gw.send(JSON.stringify({
-				type: 'init-form',
-				body: form
-			}));
-		}, 1000);
-
-		// どんな設定内容の対局でも受け入れる
-		setTimeout(() => {
-			gw.send(JSON.stringify({
-				type: 'accept'
-			}));
-		}, 2000);
-	});
-
-	gw.on('close', () => {
-		console.log('reversi game stream closed');
-	});
-}
-
-/**
- * リバーシの対局に招待されたとき
- * @param inviter 誘ってきたユーザー
- */
-async function onInviteMe(inviter) {
-	console.log(`Someone invited me: @${inviter.username}`);
-
-	// 承認
-	const game = await request.post(`${conf.api_url}/reversi/match`, {
-		json: {
-			i,
-			userId: inviter.id
-		}
-	});
-
-	gameStart(game);
-}
diff --git a/src/reversi/ai/index.ts b/src/reversi/ai/index.ts
deleted file mode 100644
index 5cd1db82d..000000000
--- a/src/reversi/ai/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-require('./front');
diff --git a/src/reversi/core.ts b/src/reversi/core.ts
index f1f9de148..37f62a43d 100644
--- a/src/reversi/core.ts
+++ b/src/reversi/core.ts
@@ -203,7 +203,7 @@ export default class Reversi {
 	 * 打つことができる場所を取得します
 	 */
 	public canPutSomewhere(color: Color): number[] {
-		const result = [];
+		const result: number[] = [];
 
 		this.board.forEach((x, i) => {
 			if (this.canPut(color, i)) result.push(i);
@@ -239,7 +239,7 @@ export default class Reversi {
 		const enemyColor = !color;
 
 		// ひっくり返せる石(の位置)リスト
-		let stones = [];
+		let stones: number[] = [];
 
 		const initPos = pos;
 
diff --git a/src/server/api/bot/core.ts b/src/server/api/bot/core.ts
deleted file mode 100644
index d41af4805..000000000
--- a/src/server/api/bot/core.ts
+++ /dev/null
@@ -1,439 +0,0 @@
-import * as EventEmitter from 'events';
-import * as bcrypt from 'bcryptjs';
-
-import User, { IUser, init as initUser, ILocalUser } from '../../../models/user';
-
-import getNoteSummary from '../../../renderers/get-note-summary';
-import getUserName from '../../../renderers/get-user-name';
-import getUserSummary from '../../../renderers/get-user-summary';
-import parseAcct from '../../../acct/parse';
-import getNotificationSummary from '../../../renderers/get-notification-summary';
-
-const hmm = [
-	'?',
-	'ふぅ~む...?',
-	'ちょっと何言ってるかわからないです',
-	'「ヘルプ」と言うと利用可能な操作が確認できますよ'
-];
-
-/**
- * Botの頭脳
- */
-export default class BotCore extends EventEmitter {
-	public user: IUser = null;
-
-	private context: Context = null;
-
-	constructor(user?: IUser) {
-		super();
-
-		this.user = user;
-	}
-
-	public clearContext() {
-		this.setContext(null);
-	}
-
-	public setContext(context: Context) {
-		this.context = context;
-		this.emit('updated');
-
-		if (context) {
-			context.on('updated', () => {
-				this.emit('updated');
-			});
-		}
-	}
-
-	public export() {
-		return {
-			user: this.user,
-			context: this.context ? this.context.export() : null
-		};
-	}
-
-	protected _import(data) {
-		this.user = data.user ? initUser(data.user) : null;
-		this.setContext(data.context ? Context.import(this, data.context) : null);
-	}
-
-	public static import(data) {
-		const bot = new BotCore();
-		bot._import(data);
-		return bot;
-	}
-
-	public async q(query: string): Promise<string> {
-		if (this.context != null) {
-			return await this.context.q(query);
-		}
-
-		if (/^@[a-zA-Z0-9_]+$/.test(query)) {
-			return await this.showUserCommand(query);
-		}
-
-		switch (query) {
-			case 'ping':
-				return 'PONG';
-
-			case 'help':
-			case 'ヘルプ':
-				return '利用可能なコマンド一覧です:\n' +
-					'help: これです\n' +
-					'me: アカウント情報を見ます\n' +
-					'login, signin: サインインします\n' +
-					'logout, signout: サインアウトします\n' +
-					'note: 投稿します\n' +
-					'tl: タイムラインを見ます\n' +
-					'no: 通知を見ます\n' +
-					'@<ユーザー名>: ユーザーを表示します\n' +
-					'\n' +
-					'タイムラインや通知を見た後、「次」というとさらに遡ることができます。';
-
-			case 'me':
-				return this.user ? `${getUserName(this.user)}としてサインインしています。\n\n${getUserSummary(this.user)}` : 'サインインしていません';
-
-			case 'login':
-			case 'signin':
-			case 'ログイン':
-			case 'サインイン':
-				if (this.user != null) return '既にサインインしていますよ!';
-				this.setContext(new SigninContext(this));
-				return await this.context.greet();
-
-			case 'logout':
-			case 'signout':
-			case 'ログアウト':
-			case 'サインアウト':
-				if (this.user == null) return '今はサインインしてないですよ!';
-				this.signout();
-				return 'ご利用ありがとうございました <3';
-
-			case 'note':
-			case '投稿':
-				if (this.user == null) return 'まずサインインしてください。';
-				this.setContext(new NoteContext(this));
-				return await this.context.greet();
-
-			case 'tl':
-			case 'タイムライン':
-				if (this.user == null) return 'まずサインインしてください。';
-				this.setContext(new TlContext(this));
-				return await this.context.greet();
-
-			case 'no':
-			case 'notifications':
-			case '通知':
-				if (this.user == null) return 'まずサインインしてください。';
-				this.setContext(new NotificationsContext(this));
-				return await this.context.greet();
-
-			case 'guessing-game':
-			case '数当てゲーム':
-				this.setContext(new GuessingGameContext(this));
-				return await this.context.greet();
-
-			default:
-				return hmm[Math.floor(Math.random() * hmm.length)];
-		}
-	}
-
-	public signin(user: IUser) {
-		this.user = user;
-		this.emit('signin', user);
-		this.emit('updated');
-	}
-
-	public signout() {
-		const user = this.user;
-		this.user = null;
-		this.emit('signout', user);
-		this.emit('updated');
-	}
-
-	public async refreshUser() {
-		this.user = await User.findOne({
-			_id: this.user._id
-		}, {
-			fields: {
-				data: false
-			}
-		});
-
-		this.emit('updated');
-	}
-
-	public async showUserCommand(q: string): Promise<string> {
-		try {
-			const user = await require('../endpoints/users/show')(parseAcct(q.substr(1)), this.user);
-
-			const text = getUserSummary(user);
-
-			return text;
-		} catch (e) {
-			return `問題が発生したようです...: ${e}`;
-		}
-	}
-}
-
-abstract class Context extends EventEmitter {
-	protected bot: BotCore;
-
-	public abstract async greet(): Promise<string>;
-	public abstract async q(query: string): Promise<string>;
-	public abstract export(): any;
-
-	constructor(bot: BotCore) {
-		super();
-		this.bot = bot;
-	}
-
-	public static import(bot: BotCore, data: any) {
-		if (data.type == 'guessing-game') return GuessingGameContext.import(bot, data.content);
-		if (data.type == 'note') return NoteContext.import(bot, data.content);
-		if (data.type == 'tl') return TlContext.import(bot, data.content);
-		if (data.type == 'notifications') return NotificationsContext.import(bot, data.content);
-		if (data.type == 'signin') return SigninContext.import(bot, data.content);
-		return null;
-	}
-}
-
-class SigninContext extends Context {
-	private temporaryUser: ILocalUser = null;
-
-	public async greet(): Promise<string> {
-		return 'まずユーザー名を教えてください:';
-	}
-
-	public async q(query: string): Promise<string> {
-		if (this.temporaryUser == null) {
-			// Fetch user
-			const user = await User.findOne({
-				usernameLower: query.toLowerCase(),
-				host: null
-			}, {
-				fields: {
-					data: false
-				}
-			}) as ILocalUser;
-
-			if (user === null) {
-				return `${query}というユーザーは存在しませんでした... もう一度教えてください:`;
-			} else {
-				this.temporaryUser = user;
-				this.emit('updated');
-				return `パスワードを教えてください:`;
-			}
-		} else {
-			// Compare password
-			const same = await bcrypt.compare(query, this.temporaryUser.password);
-
-			if (same) {
-				this.bot.signin(this.temporaryUser);
-				this.bot.clearContext();
-				return `${getUserName(this.temporaryUser)}さん、おかえりなさい!`;
-			} else {
-				return `パスワードが違います... もう一度教えてください:`;
-			}
-		}
-	}
-
-	public export() {
-		return {
-			type: 'signin',
-			content: {
-				temporaryUser: this.temporaryUser
-			}
-		};
-	}
-
-	public static import(bot: BotCore, data: any) {
-		const context = new SigninContext(bot);
-		context.temporaryUser = data.temporaryUser;
-		return context;
-	}
-}
-
-class NoteContext extends Context {
-	public async greet(): Promise<string> {
-		return '内容:';
-	}
-
-	public async q(query: string): Promise<string> {
-		await require('../endpoints/notes/create')({
-			text: query
-		}, this.bot.user);
-		this.bot.clearContext();
-		return '投稿しましたよ!';
-	}
-
-	public export() {
-		return {
-			type: 'note'
-		};
-	}
-
-	public static import(bot: BotCore, data: any) {
-		const context = new NoteContext(bot);
-		return context;
-	}
-}
-
-class TlContext extends Context {
-	private next: string = null;
-
-	public async greet(): Promise<string> {
-		return await this.getTl();
-	}
-
-	public async q(query: string): Promise<string> {
-		if (query == '次') {
-			return await this.getTl();
-		} else {
-			this.bot.clearContext();
-			return await this.bot.q(query);
-		}
-	}
-
-	private async getTl() {
-		const tl = await require('../endpoints/notes/timeline')({
-			limit: 5,
-			untilId: this.next ? this.next : undefined
-		}, this.bot.user);
-
-		if (tl.length > 0) {
-			this.next = tl[tl.length - 1].id;
-			this.emit('updated');
-
-			const text = tl
-				.map(note => `${getUserName(note.user)}\n「${getNoteSummary(note)}」`)
-				.join('\n-----\n');
-
-			return text;
-		} else {
-			return 'タイムラインに表示するものがありません...';
-		}
-	}
-
-	public export() {
-		return {
-			type: 'tl',
-			content: {
-				next: this.next,
-			}
-		};
-	}
-
-	public static import(bot: BotCore, data: any) {
-		const context = new TlContext(bot);
-		context.next = data.next;
-		return context;
-	}
-}
-
-class NotificationsContext extends Context {
-	private next: string = null;
-
-	public async greet(): Promise<string> {
-		return await this.getNotifications();
-	}
-
-	public async q(query: string): Promise<string> {
-		if (query == '次') {
-			return await this.getNotifications();
-		} else {
-			this.bot.clearContext();
-			return await this.bot.q(query);
-		}
-	}
-
-	private async getNotifications() {
-		const notifications = await require('../endpoints/i/notifications')({
-			limit: 5,
-			untilId: this.next ? this.next : undefined
-		}, this.bot.user);
-
-		if (notifications.length > 0) {
-			this.next = notifications[notifications.length - 1].id;
-			this.emit('updated');
-
-			const text = notifications
-				.map(notification => getNotificationSummary(notification))
-				.join('\n-----\n');
-
-			return text;
-		} else {
-			return '通知はありません';
-		}
-	}
-
-	public export() {
-		return {
-			type: 'notifications',
-			content: {
-				next: this.next,
-			}
-		};
-	}
-
-	public static import(bot: BotCore, data: any) {
-		const context = new NotificationsContext(bot);
-		context.next = data.next;
-		return context;
-	}
-}
-
-class GuessingGameContext extends Context {
-	private secret: number;
-	private history: number[] = [];
-
-	public async greet(): Promise<string> {
-		this.secret = Math.floor(Math.random() * 100);
-		this.emit('updated');
-		return '0~100の秘密の数を当ててみてください:';
-	}
-
-	public async q(query: string): Promise<string> {
-		if (query == 'やめる') {
-			this.bot.clearContext();
-			return 'やめました。';
-		}
-
-		const guess = parseInt(query, 10);
-
-		if (isNaN(guess)) {
-			return '整数で推測してください。「やめる」と言うとゲームをやめます。';
-		}
-
-		const firsttime = this.history.indexOf(guess) === -1;
-
-		this.history.push(guess);
-		this.emit('updated');
-
-		if (this.secret < guess) {
-			return firsttime ? `${guess}よりも小さいですね` : `もう一度言いますが${guess}より小さいですよ`;
-		} else if (this.secret > guess) {
-			return firsttime ? `${guess}よりも大きいですね` : `もう一度言いますが${guess}より大きいですよ`;
-		} else {
-			this.bot.clearContext();
-			return `正解です🎉 (${this.history.length}回目で当てました)`;
-		}
-	}
-
-	public export() {
-		return {
-			type: 'guessing-game',
-			content: {
-				secret: this.secret,
-				history: this.history
-			}
-		};
-	}
-
-	public static import(bot: BotCore, data: any) {
-		const context = new GuessingGameContext(bot);
-		context.secret = data.secret;
-		context.history = data.history;
-		return context;
-	}
-}
diff --git a/src/server/api/bot/interfaces/line.ts b/src/server/api/bot/interfaces/line.ts
deleted file mode 100644
index 733315391..000000000
--- a/src/server/api/bot/interfaces/line.ts
+++ /dev/null
@@ -1,238 +0,0 @@
-import * as EventEmitter from 'events';
-import * as Router from 'koa-router';
-import * as request from 'request';
-import * as crypto from 'crypto';
-import User from '../../../../models/user';
-import config from '../../../../config';
-import BotCore from '../core';
-import _redis from '../../../../db/redis';
-import prominence = require('prominence');
-import getAcct from '../../../../acct/render';
-import parseAcct from '../../../../acct/parse';
-import getNoteSummary from '../../../../renderers/get-note-summary';
-import getUserName from '../../../../renderers/get-user-name';
-
-const redis = prominence(_redis);
-
-// SEE: https://developers.line.me/media/messaging-api/messages/sticker_list.pdf
-const stickers = [
-	'297',
-	'298',
-	'299',
-	'300',
-	'301',
-	'302',
-	'303',
-	'304',
-	'305',
-	'306',
-	'307'
-];
-
-class LineBot extends BotCore {
-	private replyToken: string;
-
-	private reply(messages: any[]) {
-		request.post({
-			url: 'https://api.line.me/v2/bot/message/reply',
-			headers: {
-				'Authorization': `Bearer ${config.line_bot.channel_access_token}`
-			},
-			json: {
-				replyToken: this.replyToken,
-				messages: messages
-			}
-		}, (err, res, body) => {
-			if (err) {
-				console.error(err);
-				return;
-			}
-		});
-	}
-
-	public async react(ev: any): Promise<void> {
-		this.replyToken = ev.replyToken;
-
-		switch (ev.type) {
-			// メッセージ
-			case 'message':
-				switch (ev.message.type) {
-					// テキスト
-					case 'text':
-						const res = await this.q(ev.message.text);
-						if (res == null) return;
-						// 返信
-						this.reply([{
-							type: 'text',
-							text: res
-						}]);
-						break;
-
-					// スタンプ
-					case 'sticker':
-						// スタンプで返信
-						this.reply([{
-							type: 'sticker',
-							packageId: '4',
-							stickerId: stickers[Math.floor(Math.random() * stickers.length)]
-						}]);
-						break;
-				}
-				break;
-
-			// noteback
-			case 'noteback':
-				const data = ev.noteback.data;
-				const cmd = data.split('|')[0];
-				const arg = data.split('|')[1];
-				switch (cmd) {
-					case 'showtl':
-						this.showUserTimelineNoteback(arg);
-						break;
-				}
-				break;
-		}
-	}
-
-	public static import(data) {
-		const bot = new LineBot();
-		bot._import(data);
-		return bot;
-	}
-
-	public async showUserCommand(q: string) {
-		const user = await require('../../endpoints/users/show')(parseAcct(q.substr(1)), this.user);
-
-		const acct = getAcct(user);
-		const actions = [];
-
-		actions.push({
-			type: 'noteback',
-			label: 'タイムラインを見る',
-			data: `showtl|${user.id}`
-		});
-
-		if (user.twitter) {
-			actions.push({
-				type: 'uri',
-				label: 'Twitterアカウントを見る',
-				uri: `https://twitter.com/${user.twitter.screenName}`
-			});
-		}
-
-		actions.push({
-			type: 'uri',
-			label: 'Webで見る',
-			uri: `${config.url}/@${acct}`
-		});
-
-		this.reply([{
-			type: 'template',
-			altText: await super.showUserCommand(q),
-			template: {
-				type: 'buttons',
-				thumbnailImageUrl: `${user.avatarUrl}?thumbnail&size=1024`,
-				title: `${getUserName(user)} (@${acct})`,
-				text: user.description || '(no description)',
-				actions: actions
-			}
-		}]);
-
-		return null;
-	}
-
-	public async showUserTimelineNoteback(userId: string) {
-		const tl = await require('../../endpoints/users/notes')({
-			userId: userId,
-			limit: 5
-		}, this.user);
-
-		const text = `${getUserName(tl[0].user)}さんのタイムラインはこちらです:\n\n` + tl
-			.map(note => getNoteSummary(note))
-			.join('\n-----\n');
-
-		this.reply([{
-			type: 'text',
-			text: text
-		}]);
-	}
-}
-
-const handler = new EventEmitter();
-
-handler.on('event', async (ev) => {
-
-	const sourceId = ev.source.userId;
-	const sessionId = `line-bot-sessions:${sourceId}`;
-
-	const session = await redis.get(sessionId);
-	let bot: LineBot;
-
-	if (session == null) {
-		const user = await User.findOne({
-			host: null,
-			'line': {
-				userId: sourceId
-			}
-		});
-
-		bot = new LineBot(user);
-
-		bot.on('signin', user => {
-			User.update(user._id, {
-				$set: {
-					'line': {
-						userId: sourceId
-					}
-				}
-			});
-		});
-
-		bot.on('signout', user => {
-			User.update(user._id, {
-				$set: {
-					'line': {
-						userId: null
-					}
-				}
-			});
-		});
-
-		redis.set(sessionId, JSON.stringify(bot.export()));
-	} else {
-		bot = LineBot.import(JSON.parse(session));
-	}
-
-	bot.on('updated', () => {
-		redis.set(sessionId, JSON.stringify(bot.export()));
-	});
-
-	if (session != null) bot.refreshUser();
-
-	bot.react(ev);
-});
-
-// Init router
-const router = new Router();
-
-if (config.line_bot) {
-	router.post('/hooks/line', ctx => {
-		const sig1 = ctx.headers['x-line-signature'];
-
-		const hash = crypto.createHmac('SHA256', config.line_bot.channel_secret)
-			.update(ctx.request.rawBody);
-
-		const sig2 = hash.digest('base64');
-
-		// シグネチャ比較
-		if (sig1 === sig2) {
-			ctx.request.body.events.forEach(ev => {
-				handler.emit('event', ev);
-			});
-		} else {
-			ctx.status = 400;
-		}
-	});
-}
-
-module.exports = router;
diff --git a/src/server/api/common/get-host-lower.ts b/src/server/api/common/get-host-lower.ts
index 550c23300..92704b4aa 100644
--- a/src/server/api/common/get-host-lower.ts
+++ b/src/server/api/common/get-host-lower.ts
@@ -1,5 +1,5 @@
 import { toUnicode } from 'punycode';
 
-export default host => {
+export default (host: string) => {
 	return toUnicode(host).toLowerCase();
 };
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts
index d348cadae..9ada9cd3f 100644
--- a/src/server/api/endpoints/aggregation/posts.ts
+++ b/src/server/api/endpoints/aggregation/posts.ts
@@ -1,13 +1,10 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import Note from '../../../../models/note';
 
 /**
  * Aggregate notes
  */
-module.exports = params => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts
index b116c1454..c084404d0 100644
--- a/src/server/api/endpoints/aggregation/users.ts
+++ b/src/server/api/endpoints/aggregation/users.ts
@@ -1,13 +1,10 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import User from '../../../../models/user';
 
 /**
  * Aggregate users
  */
-module.exports = params => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts
index 9109487ac..d4c716d65 100644
--- a/src/server/api/endpoints/aggregation/users/activity.ts
+++ b/src/server/api/endpoints/aggregation/users/activity.ts
@@ -1,6 +1,3 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Note from '../../../../../models/note';
@@ -10,7 +7,7 @@ import Note from '../../../../../models/note';
 /**
  * Aggregate activity of a user
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
@@ -73,13 +70,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
 			} }
 		]);
 
-	datas.forEach(data => {
+	datas.forEach((data: any) => {
 		data.date = data._id;
 		delete data._id;
 
-		data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count;
-		data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count;
-		data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count;
+		data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
+		data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
+		data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
 
 		delete data.data;
 	});
@@ -89,7 +86,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	for (let i = 0; i < limit; i++) {
 		const day = new Date(new Date().setDate(new Date().getDate() - i));
 
-		const data = datas.filter(d =>
+		const data = datas.filter((d: any) =>
 			d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
 		)[0];
 
diff --git a/src/server/api/endpoints/aggregation/users/followers.ts b/src/server/api/endpoints/aggregation/users/followers.ts
index dfcaf8462..847f37607 100644
--- a/src/server/api/endpoints/aggregation/users/followers.ts
+++ b/src/server/api/endpoints/aggregation/users/followers.ts
@@ -8,7 +8,7 @@ import FollowedLog from '../../../../../models/followed-log';
 /**
  * Aggregate followers of a user
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/aggregation/users/following.ts b/src/server/api/endpoints/aggregation/users/following.ts
index 5f826fd71..6c52752f9 100644
--- a/src/server/api/endpoints/aggregation/users/following.ts
+++ b/src/server/api/endpoints/aggregation/users/following.ts
@@ -8,7 +8,7 @@ import FollowingLog from '../../../../../models/following-log';
 /**
  * Aggregate following of a user
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/aggregation/users/post.ts b/src/server/api/endpoints/aggregation/users/post.ts
index 11f9ef14c..28ba1482b 100644
--- a/src/server/api/endpoints/aggregation/users/post.ts
+++ b/src/server/api/endpoints/aggregation/users/post.ts
@@ -1,6 +1,3 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Note from '../../../../../models/note';
@@ -8,7 +5,7 @@ import Note from '../../../../../models/note';
 /**
  * Aggregate note of a user
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
@@ -67,13 +64,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
 			} }
 		]);
 
-	datas.forEach(data => {
+	datas.forEach((data: any) => {
 		data.date = data._id;
 		delete data._id;
 
-		data.notes = (data.data.filter(x => x.type == 'note')[0] || { count: 0 }).count;
-		data.renotes = (data.data.filter(x => x.type == 'renote')[0] || { count: 0 }).count;
-		data.replies = (data.data.filter(x => x.type == 'reply')[0] || { count: 0 }).count;
+		data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
+		data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
+		data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
 
 		delete data.data;
 	});
@@ -83,7 +80,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	for (let i = 0; i < 30; i++) {
 		const day = new Date(new Date().setDate(new Date().getDate() - i));
 
-		const data = datas.filter(d =>
+		const data = datas.filter((d: any) =>
 			d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
 		)[0];
 
diff --git a/src/server/api/endpoints/aggregation/users/reaction.ts b/src/server/api/endpoints/aggregation/users/reaction.ts
index 2de284025..adb5acfb4 100644
--- a/src/server/api/endpoints/aggregation/users/reaction.ts
+++ b/src/server/api/endpoints/aggregation/users/reaction.ts
@@ -1,17 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import User from '../../../../../models/user';
 import Reaction from '../../../../../models/note-reaction';
 
 /**
  * Aggregate reaction of a user
- *
- * @param {any} params
- * @return {Promise<any>}
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
@@ -48,7 +42,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 			}}
 		]);
 
-	datas.forEach(data => {
+	datas.forEach((data: any) => {
 		data.date = data._id;
 		delete data._id;
 	});
@@ -58,7 +52,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	for (let i = 0; i < 30; i++) {
 		const day = new Date(new Date().setDate(new Date().getDate() - i));
 
-		const data = datas.filter(d =>
+		const data = datas.filter((d: any) =>
 			d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
 		)[0];
 
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index 553bd2381..c7bc91a07 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -1,9 +1,7 @@
-/**
- * Module dependencies
- */
 import rndstr from 'rndstr';
 import $ from 'cafy';
 import App, { isValidNameId, pack } from '../../../../models/app';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * @swagger
@@ -60,12 +58,8 @@ import App, { isValidNameId, pack } from '../../../../models/app';
 
 /**
  * Create an app
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'nameId' parameter
 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
diff --git a/src/server/api/endpoints/app/name_id/available.ts b/src/server/api/endpoints/app/name_id/available.ts
index 135bb7d2b..58101a7e6 100644
--- a/src/server/api/endpoints/app/name_id/available.ts
+++ b/src/server/api/endpoints/app/name_id/available.ts
@@ -40,7 +40,7 @@ import { isValidNameId } from '../../../../../models/app';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = async (params) => new Promise(async (res, rej) => {
+module.exports = async (params: any) => new Promise(async (res, rej) => {
 	// Get 'nameId' parameter
 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index 8d742ab18..2b98a3f14 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -1,8 +1,6 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import App, { pack } from '../../../../models/app';
+import App, { pack, IApp } from '../../../../models/app';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * @swagger
@@ -37,7 +35,7 @@ import App, { pack } from '../../../../models/app';
 /**
  * Show an app
  */
-module.exports = (params, user, app) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	// Get 'appId' parameter
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
index 695fbb080..fc6cbc473 100644
--- a/src/server/api/endpoints/auth/accept.ts
+++ b/src/server/api/endpoints/auth/accept.ts
@@ -1,12 +1,10 @@
-/**
- * Module dependencies
- */
 import rndstr from 'rndstr';
 const crypto = require('crypto');
 import $ from 'cafy';
 import App from '../../../../models/app';
 import AuthSess from '../../../../models/auth-session';
 import AccessToken from '../../../../models/access-token';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * @swagger
@@ -33,12 +31,8 @@ import AccessToken from '../../../../models/access-token';
 
 /**
  * Accept
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts
index d649a8d90..5a4d99ff3 100644
--- a/src/server/api/endpoints/auth/session/generate.ts
+++ b/src/server/api/endpoints/auth/session/generate.ts
@@ -44,7 +44,7 @@ import config from '../../../../../config';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'appSecret' parameter
 	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
 	if (appSecretErr) return rej('invalid appSecret param');
diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts
index 434cc264a..3d3b6bbf6 100644
--- a/src/server/api/endpoints/auth/session/show.ts
+++ b/src/server/api/endpoints/auth/session/show.ts
@@ -1,8 +1,6 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import AuthSess, { pack } from '../../../../../models/auth-session';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * @swagger
@@ -46,12 +44,8 @@ import AuthSess, { pack } from '../../../../../models/auth-session';
 
 /**
  * Show a session
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
index 3026b477f..3ea48fbe3 100644
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ b/src/server/api/endpoints/auth/session/userkey.ts
@@ -49,7 +49,7 @@ import { pack } from '../../../../../models/user';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'appSecret' parameter
 	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
 	if (appSecretErr) return rej('invalid appSecret param');
diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts
index 26944dbc1..9caad273c 100644
--- a/src/server/api/endpoints/drive.ts
+++ b/src/server/api/endpoints/drive.ts
@@ -1,9 +1,10 @@
 import DriveFile from '../../../models/drive-file';
+import { ILocalUser } from '../../../models/user';
 
 /**
  * Get drive information
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Calculate drive usage
 	const usage = await DriveFile
 		.aggregate([{
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index 0f0e3d65a..efce75074 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import DriveFile, { pack } from '../../../../models/drive-file';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get drive files
  */
-module.exports = async (params, user, app) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index dd748d6bb..db2626af0 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import * as fs from 'fs';
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import { validateFileName, pack } from '../../../../../models/drive-file';
 import create from '../../../../../services/drive/add-file';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Create a file
  */
-module.exports = async (file, params, user): Promise<any> => {
+module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> => {
 	if (file == null) {
 		throw 'file is required';
 	}
diff --git a/src/server/api/endpoints/drive/files/delete.ts b/src/server/api/endpoints/drive/files/delete.ts
index a722b4e82..17eb0eb4b 100644
--- a/src/server/api/endpoints/drive/files/delete.ts
+++ b/src/server/api/endpoints/drive/files/delete.ts
@@ -2,11 +2,12 @@ import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFile from '../../../../../models/drive-file';
 import del from '../../../../../services/drive/delete-file';
 import { publishDriveStream } from '../../../../../publishers/stream';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Delete a file
  */
-module.exports = async (params, user) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) throw 'invalid fileId param';
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index 98165990f..75ab91f0a 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFile, { pack } from '../../../../../models/drive-file';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Find a file(s)
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
index c7efda7ab..e7dca486c 100644
--- a/src/server/api/endpoints/drive/files/show.ts
+++ b/src/server/api/endpoints/drive/files/show.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFile, { pack } from '../../../../../models/drive-file';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Show a file
  */
-module.exports = async (params, user) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) throw 'invalid fileId param';
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index 12fa8e025..825683b21 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder from '../../../../../models/drive-folder';
 import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
 import { publishDriveStream } from '../../../../../publishers/stream';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Update a file
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) return rej('invalid fileId param');
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index bc6c50eb9..fac978032 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -7,7 +7,7 @@ import DriveFolder, { pack } from '../../../../models/drive-folder';
 /**
  * Get drive folders
  */
-module.exports = (params, user, app) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts
index 62e3b6f6e..8f06b0f66 100644
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ b/src/server/api/endpoints/drive/folders/create.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
 import { publishDriveStream } from '../../../../../publishers/stream';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Create drive folder
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
index 9703d9e99..b3238b5c3 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { pack } from '../../../../../models/drive-folder';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Find a folder(s)
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts
index 44f188900..c9b4930a7 100644
--- a/src/server/api/endpoints/drive/folders/show.ts
+++ b/src/server/api/endpoints/drive/folders/show.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { pack } from '../../../../../models/drive-folder';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Show a folder
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
 	const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index e24d8a14c..f126c09f5 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
 import { publishDriveStream } from '../../../../../publishers/stream';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Update a folder
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
 	const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
@@ -48,7 +46,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 			}
 
 			// Check if the circular reference will occur
-			async function checkCircle(folderId) {
+			async function checkCircle(folderId: any): Promise<boolean> {
 				// Fetch folder
 				const folder2 = await DriveFolder.findOne({
 					_id: folderId
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 8cb3a99b4..515f74645 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import DriveFile, { pack } from '../../../../models/drive-file';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get drive stream
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts
index b9610658d..3e45b8da5 100644
--- a/src/server/api/endpoints/following/create.ts
+++ b/src/server/api/endpoints/following/create.ts
@@ -1,15 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import create from '../../../../services/following/create';
 
 /**
  * Follow a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts
index 4fcdaf5a8..0af8813cf 100644
--- a/src/server/api/endpoints/following/delete.ts
+++ b/src/server/api/endpoints/following/delete.ts
@@ -1,15 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import deleteFollowing from '../../../../services/following/delete';
 
 /**
  * Unfollow a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/requests/accept.ts b/src/server/api/endpoints/following/requests/accept.ts
index 705d3b161..a09e32e4d 100644
--- a/src/server/api/endpoints/following/requests/accept.ts
+++ b/src/server/api/endpoints/following/requests/accept.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import acceptFollowRequest from '../../../../../services/following/requests/accept';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 
 /**
  * Accept a follow request
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followerId, followerIdErr] = $.type(ID).get(params.userId);
 	if (followerIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/requests/cancel.ts b/src/server/api/endpoints/following/requests/cancel.ts
index 388a54890..f2a40854c 100644
--- a/src/server/api/endpoints/following/requests/cancel.ts
+++ b/src/server/api/endpoints/following/requests/cancel.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import cancelFollowRequest from '../../../../../services/following/requests/cancel';
-import User, { pack } from '../../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../../models/user';
 
 /**
  * Cancel a follow request
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followeeId, followeeIdErr] = $.type(ID).get(params.userId);
 	if (followeeIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/requests/list.ts b/src/server/api/endpoints/following/requests/list.ts
index e8364335d..287c5a8e4 100644
--- a/src/server/api/endpoints/following/requests/list.ts
+++ b/src/server/api/endpoints/following/requests/list.ts
@@ -1,10 +1,11 @@
 //import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import FollowRequest, { pack } from '../../../../../models/follow-request';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Get all pending received follow requests
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const reqs = await FollowRequest.find({
 		followeeId: user._id
 	});
diff --git a/src/server/api/endpoints/following/requests/reject.ts b/src/server/api/endpoints/following/requests/reject.ts
index 1cfb562b5..69dddf135 100644
--- a/src/server/api/endpoints/following/requests/reject.ts
+++ b/src/server/api/endpoints/following/requests/reject.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import rejectFollowRequest from '../../../../../services/following/requests/reject';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 
 /**
  * Reject a follow request
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followerId, followerIdErr] = $.type(ID).get(params.userId);
 	if (followerIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts
index f0bc8cbdf..b9d19d57b 100644
--- a/src/server/api/endpoints/following/stalk.ts
+++ b/src/server/api/endpoints/following/stalk.ts
@@ -1,10 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Following from '../../../../models/following';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Stalk a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts
index 0d0a018c3..255f22ca1 100644
--- a/src/server/api/endpoints/following/unstalk.ts
+++ b/src/server/api/endpoints/following/unstalk.ts
@@ -1,10 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Following from '../../../../models/following';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Unstalk a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
index 947dd6e44..17af9d6a9 100644
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ b/src/server/api/endpoints/hashtags/trend.ts
@@ -45,7 +45,10 @@ module.exports = () => new Promise(async (res, rej) => {
 		return res([]);
 	}
 
-	const tags = [];
+	const tags: Array<{
+		name: string;
+		count: number;
+	}> = [];
 
 	// カウント
 	data.map(x => x._id).forEach(x => {
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index 379c3c4d8..5c769a02f 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -1,12 +1,10 @@
-/**
- * Module dependencies
- */
-import User, { pack } from '../../../models/user';
+import User, { pack, ILocalUser } from '../../../models/user';
+import { IApp } from '../../../models/app';
 
 /**
  * Show myself
  */
-module.exports = (params, user, app) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	// Serialize
diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts
index 1a2706aa8..61f13c4c6 100644
--- a/src/server/api/endpoints/i/2fa/done.ts
+++ b/src/server/api/endpoints/i/2fa/done.ts
@@ -1,11 +1,8 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import * as speakeasy from 'speakeasy';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts
index d314e1a28..d05892c84 100644
--- a/src/server/api/endpoints/i/2fa/register.ts
+++ b/src/server/api/endpoints/i/2fa/register.ts
@@ -1,14 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import * as speakeasy from 'speakeasy';
 import * as QRCode from 'qrcode';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 import config from '../../../../../config';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts
index 336a3564a..fc197cb1e 100644
--- a/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/src/server/api/endpoints/i/2fa/unregister.ts
@@ -1,11 +1,8 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index d15bd67bf..cfc93c151 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import AccessToken from '../../../../models/access-token';
 import { pack } from '../../../../models/app';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get authorized apps of my account
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts
index a1a1a4340..9851fa895 100644
--- a/src/server/api/endpoints/i/change_password.ts
+++ b/src/server/api/endpoints/i/change_password.ts
@@ -1,14 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 
 /**
  * Change password
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'currentPasword' parameter
 	const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword);
 	if (currentPasswordErr) return rej('invalid currentPasword param');
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index 23517baaf..dc343afae 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Favorite, { pack } from '../../../../models/favorite';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get favorited notes
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index ba9c47508..ce283fe48 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -1,17 +1,15 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Notification from '../../../../models/notification';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/notification';
 import { getFriendIds } from '../../common/get-friends';
 import read from '../../common/read-notification';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get notifications
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
 		$.bool.optional().get(params.following);
diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts
index 423f0ac4a..7f4a45e1f 100644
--- a/src/server/api/endpoints/i/pin.ts
+++ b/src/server/api/endpoints/i/pin.ts
@@ -1,15 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Note from '../../../../models/note';
 import { pack } from '../../../../models/user';
 
 /**
  * Pin note
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts
index 6e1e57129..3ffab5428 100644
--- a/src/server/api/endpoints/i/regenerate_token.ts
+++ b/src/server/api/endpoints/i/regenerate_token.ts
@@ -1,16 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 import generateUserToken from '../../common/generate-native-user-token';
 
 /**
  * Regenerate native token
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts
index 63a74b41b..4ab9881f3 100644
--- a/src/server/api/endpoints/i/signin_history.ts
+++ b/src/server/api/endpoints/i/signin_history.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Signin, { pack } from '../../../../models/signin';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get signin history of my account
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 1a1da997c..57b050ebc 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -1,16 +1,14 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../../../models/user';
+import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 import DriveFile from '../../../../models/drive-file';
 import acceptAllFollowRequests from '../../../../services/following/requests/accept-all';
+import { IApp } from '../../../../models/app';
 
 /**
  * Update myself
  */
-module.exports = async (params, user, app) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	const updates = {} as any;
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index e91d7565f..6d6e8ed24 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -1,14 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
 /**
  * Update myself
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
@@ -17,7 +14,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	const [value, valueErr] = $.any.nullable().get(params.value);
 	if (valueErr) return rej('invalid value param');
 
-	const x = {};
+	const x: any = {};
 	x[`clientSettings.${name}`] = value;
 
 	await User.update(user._id, {
diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts
index 48f6dbbb7..511a647d8 100644
--- a/src/server/api/endpoints/i/update_home.ts
+++ b/src/server/api/endpoints/i/update_home.ts
@@ -1,8 +1,8 @@
 import $ from 'cafy';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $.arr(
 		$.obj.strict()
diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts
index d285a0a72..b1f25624f 100644
--- a/src/server/api/endpoints/i/update_mobile_home.ts
+++ b/src/server/api/endpoints/i/update_mobile_home.ts
@@ -1,8 +1,8 @@
 import $ from 'cafy';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $.arr(
 		$.obj.strict()
diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts
index b37761bde..82bb04d1f 100644
--- a/src/server/api/endpoints/i/update_widget.ts
+++ b/src/server/api/endpoints/i/update_widget.ts
@@ -1,8 +1,8 @@
 import $ from 'cafy';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'id' parameter
 	const [id, idErr] = $.str.get(params.id);
 	if (idErr) return rej('invalid id param');
@@ -18,7 +18,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	//#region Desktop home
 	if (widget == null && user.clientSettings.home) {
 		const desktopHome = user.clientSettings.home;
-		widget = desktopHome.find(w => w.id == id);
+		widget = desktopHome.find((w: any) => w.id == id);
 		if (widget) {
 				widget.data = data;
 
@@ -34,7 +34,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	//#region Mobile home
 	if (widget == null && user.clientSettings.mobileHome) {
 		const mobileHome = user.clientSettings.mobileHome;
-		widget = mobileHome.find(w => w.id == id);
+		widget = mobileHome.find((w: any) => w.id == id);
 		if (widget) {
 				widget.data = data;
 
@@ -50,8 +50,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	//#region Deck
 	if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
 		const deck = user.clientSettings.deck;
-		deck.columns.filter(c => c.type == 'widgets').forEach(c => {
-			c.widgets.forEach(w => {
+		deck.columns.filter((c: any) => c.type == 'widgets').forEach((c: any) => {
+			c.widgets.forEach((w: any) => {
 				if (w.id == id) widget = w;
 			});
 		});
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index ec97642f1..713ba9dd7 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import History from '../../../../models/messaging-history';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/messaging-message';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Show messaging history
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index 9c3a48334..3eb20ec06 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -1,13 +1,13 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Message from '../../../../models/messaging-message';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import { pack } from '../../../../models/messaging-message';
 import read from '../../common/read-messaging-message';
 
 /**
  * Get messages
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
 	if (recipientIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
index 41238de1e..b3e4f6a8c 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -1,11 +1,8 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Message from '../../../../../models/messaging-message';
 import { isValidText } from '../../../../../models/messaging-message';
 import History from '../../../../../models/messaging-history';
-import User from '../../../../../models/user';
+import User, { ILocalUser } from '../../../../../models/user';
 import Mute from '../../../../../models/mute';
 import DriveFile from '../../../../../models/drive-file';
 import { pack } from '../../../../../models/messaging-message';
@@ -17,7 +14,7 @@ import config from '../../../../../config';
 /**
  * Create a message
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
 	if (recipientIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 0e9ecf47d..ce460d0b8 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -38,7 +38,7 @@ const client = require('../../../../built/client/meta.json');
 /**
  * Show core info
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	const meta: any = (await Meta.findOne()) || {};
 
 	res({
diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts
index 534020c67..415745e2c 100644
--- a/src/server/api/endpoints/mute/create.ts
+++ b/src/server/api/endpoints/mute/create.ts
@@ -1,14 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Mute from '../../../../models/mute';
 
 /**
  * Mute a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts
index 949aff64b..2d1d28658 100644
--- a/src/server/api/endpoints/mute/delete.ts
+++ b/src/server/api/endpoints/mute/delete.ts
@@ -1,14 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Mute from '../../../../models/mute';
 
 /**
  * Unmute a user
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index cf89f7e95..8b0171be3 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -1,15 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Mute from '../../../../models/mute';
-import { pack } from '../../../../models/user';
+import { pack, ILocalUser } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
 
 /**
  * Get muted users of a user
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'iknow' parameter
 	const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index 086e0b896..7687afd0c 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import App, { pack } from '../../../../models/app';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get my apps
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index e6fe80ac8..5554e53aa 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -7,7 +7,7 @@ import Note, { pack } from '../../../models/note';
 /**
  * Get all notes
  */
-module.exports = (params) => new Promise(async (res, rej) => {
+module.exports = (params: any) => new Promise(async (res, rej) => {
 	// Get 'local' parameter
 	const [local, localErr] = $.bool.optional().get(params.local);
 	if (localErr) return rej('invalid local param');
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index 02f7229cc..b2bc6a2e7 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import Note, { pack } from '../../../../models/note';
+import Note, { pack, INote } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Show conversation of a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
@@ -29,10 +27,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		return rej('note not found');
 	}
 
-	const conversation = [];
+	const conversation: INote[] = [];
 	let i = 0;
 
-	async function get(id) {
+	async function get(id: any) {
 		i++;
 		const p = await Note.findOne({ _id: id });
 
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 446764e1d..64f3b5ce2 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -1,9 +1,6 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
-import User, { ILocalUser } from '../../../../models/user';
+import User, { ILocalUser, IUser } from '../../../../models/user';
 import DriveFile from '../../../../models/drive-file';
 import create from '../../../../services/note/create';
 import { IApp } from '../../../../models/app';
@@ -11,7 +8,7 @@ import { IApp } from '../../../../models/app';
 /**
  * Create a note
  */
-module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	// Get 'visibility' parameter
 	const [visibility = 'public', visibilityErr] = $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']).get(params.visibility);
 	if (visibilityErr) return rej('invalid visibility');
@@ -20,7 +17,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	const [visibleUserIds, visibleUserIdsErr] = $.arr($.type(ID)).optional().unique().min(1).get(params.visibleUserIds);
 	if (visibleUserIdsErr) return rej('invalid visibleUserIds');
 
-	let visibleUsers = [];
+	let visibleUsers: IUser[] = [];
 	if (visibleUserIds !== undefined) {
 		visibleUsers = await Promise.all(visibleUserIds.map(id => User.findOne({
 			_id: id
@@ -132,7 +129,7 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res
 	if (pollErr) return rej('invalid poll');
 
 	if (poll) {
-		(poll as any).choices = (poll as any).choices.map((choice, i) => ({
+		(poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({
 			id: i, // IDを付与
 			text: choice.trim(),
 			votes: 0
diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts
index 9bbb1541d..70bcdbaab 100644
--- a/src/server/api/endpoints/notes/delete.ts
+++ b/src/server/api/endpoints/notes/delete.ts
@@ -1,11 +1,12 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import deleteNote from '../../../../services/note/delete';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Delete a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts
index 6832b52f7..23f7ac5f8 100644
--- a/src/server/api/endpoints/notes/favorites/create.ts
+++ b/src/server/api/endpoints/notes/favorites/create.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Favorite from '../../../../../models/favorite';
 import Note from '../../../../../models/note';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Favorite a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts
index 07112dae1..7d2d2b4cb 100644
--- a/src/server/api/endpoints/notes/favorites/delete.ts
+++ b/src/server/api/endpoints/notes/favorites/delete.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Favorite from '../../../../../models/favorite';
 import Note from '../../../../../models/note';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Unfavorite a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 2d4f2b636..24ffdbcba 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get timeline of global
  */
-module.exports = async (params, user) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 734cc9af0..48490638d 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get timeline of local
  */
-module.exports = async (params, user) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 163a6b486..45511603a 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -1,19 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import { getFriendIds } from '../../common/get-friends';
 import { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get mentions of myself
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
 		$.bool.optional().get(params.following);
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index a272378d1..640140c3d 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import Vote from '../../../../../models/poll-vote';
 import Note, { pack } from '../../../../../models/note';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Get recommended polls
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts
index f8f451530..72ac6bb20 100644
--- a/src/server/api/endpoints/notes/polls/vote.ts
+++ b/src/server/api/endpoints/notes/polls/vote.ts
@@ -1,6 +1,3 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Vote from '../../../../../models/poll-vote';
 import Note from '../../../../../models/note';
@@ -8,11 +5,12 @@ import Watching from '../../../../../models/note-watching';
 import watch from '../../../../../services/note/watch';
 import { publishNoteStream } from '../../../../../publishers/stream';
 import notify from '../../../../../publishers/notify';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Vote poll of a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
@@ -58,8 +56,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Send response
 	res();
 
-	const inc = {};
-	inc[`poll.choices.${findWithAttr(note.poll.choices, 'id', choice)}.votes`] = 1;
+	const inc: any = {};
+	inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == choice)}.votes`] = 1;
 
 	// Increment votes count
 	await Note.update({ _id: note._id }, {
@@ -100,12 +98,3 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		watch(user._id, note);
 	}
 });
-
-function findWithAttr(array, attr, value) {
-	for (let i = 0; i < array.length; i += 1) {
-		if (array[i][attr] === value) {
-			return i;
-		}
-	}
-	return -1;
-}
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index 4ad952a7a..d3b2d4343 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -1,18 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Reaction, { pack } from '../../../../models/note-reaction';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Show reactions of a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts
index 21757cb42..33e457e30 100644
--- a/src/server/api/endpoints/notes/reactions/create.ts
+++ b/src/server/api/endpoints/notes/reactions/create.ts
@@ -1,15 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Note from '../../../../../models/note';
 import create from '../../../../../services/note/reaction/create';
 import { validateReaction } from '../../../../../models/note-reaction';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * React to a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts
index afb862911..1f2d66251 100644
--- a/src/server/api/endpoints/notes/reactions/delete.ts
+++ b/src/server/api/endpoints/notes/reactions/delete.ts
@@ -1,14 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import Reaction from '../../../../../models/note-reaction';
 import Note from '../../../../../models/note';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Unreact to a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
@@ -45,7 +43,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Send response
 	res();
 
-	const dec = {};
+	const dec: any = {};
 	dec[`reactionCounts.${exist.reaction}`] = -1;
 
 	// Decrement reactions count
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 608027f6b..4aaf1d322 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -1,10 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get replies of a note
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts
index 3098211b6..ea3f174e1 100644
--- a/src/server/api/endpoints/notes/reposts.ts
+++ b/src/server/api/endpoints/notes/reposts.ts
@@ -1,17 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Show a renotes of a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
deleted file mode 100644
index 9705dcfd6..000000000
--- a/src/server/api/endpoints/notes/search.ts
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- * Module dependencies
- */
-import $ from 'cafy'; import ID from '../../../../cafy-id';
-const escapeRegexp = require('escape-regexp');
-import Note from '../../../../models/note';
-import User from '../../../../models/user';
-import Mute from '../../../../models/mute';
-import { getFriendIds } from '../../common/get-friends';
-import { pack } from '../../../../models/note';
-
-/**
- * Search a note
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
- */
-module.exports = (params, me) => new Promise(async (res, rej) => {
-	// Get 'text' parameter
-	const [text, textError] = $.str.optional().get(params.text);
-	if (textError) return rej('invalid text param');
-
-	// Get 'includeUserIds' parameter
-	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);
-	if (excludeUserIdsErr) return rej('invalid excludeUserIds param');
-
-	// Get 'includeUserUsernames' parameter
-	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);
-	if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param');
-
-	// Get 'following' parameter
-	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);
-	if (muteErr) return rej('invalid mute param');
-
-	// Get 'reply' parameter
-	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);
-	if (renoteErr) return rej('invalid renote param');
-
-	// Get 'media' parameter
-	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);
-	if (pollErr) return rej('invalid poll param');
-
-	// Get 'sinceDate' parameter
-	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);
-	if (untilDateErr) throw 'invalid untilDate param';
-
-	// Get 'offset' parameter
-	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);
-	if (limitErr) return rej('invalid limit param');
-
-	let includeUsers = includeUserIds;
-	if (includeUserUsernames != null) {
-		const ids = (await Promise.all(includeUserUsernames.map(async (username) => {
-			const _user = await User.findOne({
-				usernameLower: username.toLowerCase()
-			});
-			return _user ? _user._id : null;
-		}))).filter(id => id != null);
-		includeUsers = includeUsers.concat(ids);
-	}
-
-	let excludeUsers = excludeUserIds;
-	if (excludeUserUsernames != null) {
-		const ids = (await Promise.all(excludeUserUsernames.map(async (username) => {
-			const _user = await User.findOne({
-				usernameLower: username.toLowerCase()
-			});
-			return _user ? _user._id : null;
-		}))).filter(id => id != null);
-		excludeUsers = excludeUsers.concat(ids);
-	}
-
-	search(res, rej, me, text, includeUsers, excludeUsers, following,
-			mute, reply, renote, media, poll, sinceDate, untilDate, offset, limit);
-});
-
-async function search(
-	res, rej, me, text, includeUserIds, excludeUserIds, following,
-	mute, reply, renote, media, poll, sinceDate, untilDate, offset, max) {
-
-	let q: any = {
-		$and: []
-	};
-
-	const push = x => q.$and.push(x);
-
-	if (text) {
-		// 完全一致検索
-		if (/"""(.+?)"""/.test(text)) {
-			const x = text.match(/"""(.+?)"""/)[1];
-			push({
-				text: x
-			});
-		} else {
-			const tags = text.split(' ').filter(x => x[0] == '#');
-			if (tags) {
-				push({
-					$and: tags.map(x => ({
-						tags: x
-					}))
-				});
-			}
-
-			push({
-				$and: text.split(' ').map(x => ({
-					// キーワードが-で始まる場合そのキーワードを除外する
-					text: x[0] == '-' ? {
-						$not: new RegExp(escapeRegexp(x.substr(1)))
-					} : new RegExp(escapeRegexp(x))
-				}))
-			});
-		}
-	}
-
-	if (includeUserIds && includeUserIds.length != 0) {
-		push({
-			userId: {
-				$in: includeUserIds
-			}
-		});
-	} else if (excludeUserIds && excludeUserIds.length != 0) {
-		push({
-			userId: {
-				$nin: excludeUserIds
-			}
-		});
-	}
-
-	if (following != null && me != null) {
-		const ids = await getFriendIds(me._id, false);
-		push({
-			userId: following ? {
-				$in: ids
-			} : {
-				$nin: ids.concat(me._id)
-			}
-		});
-	}
-
-	if (me != null) {
-		const mutes = await Mute.find({
-			muterId: me._id,
-			deletedAt: { $exists: false }
-		});
-		const mutedUserIds = mutes.map(m => m.muteeId);
-
-		switch (mute) {
-			case 'mute_all':
-				push({
-					userId: {
-						$nin: mutedUserIds
-					},
-					'_reply.userId': {
-						$nin: mutedUserIds
-					},
-					'_renote.userId': {
-						$nin: mutedUserIds
-					}
-				});
-				break;
-			case 'mute_related':
-				push({
-					'_reply.userId': {
-						$nin: mutedUserIds
-					},
-					'_renote.userId': {
-						$nin: mutedUserIds
-					}
-				});
-				break;
-			case 'mute_direct':
-				push({
-					userId: {
-						$nin: mutedUserIds
-					}
-				});
-				break;
-			case 'direct_only':
-				push({
-					userId: {
-						$in: mutedUserIds
-					}
-				});
-				break;
-			case 'related_only':
-				push({
-					$or: [{
-						'_reply.userId': {
-							$in: mutedUserIds
-						}
-					}, {
-						'_renote.userId': {
-							$in: mutedUserIds
-						}
-					}]
-				});
-				break;
-			case 'all_only':
-				push({
-					$or: [{
-						userId: {
-							$in: mutedUserIds
-						}
-					}, {
-						'_reply.userId': {
-							$in: mutedUserIds
-						}
-					}, {
-						'_renote.userId': {
-							$in: mutedUserIds
-						}
-					}]
-				});
-				break;
-		}
-	}
-
-	if (reply != null) {
-		if (reply) {
-			push({
-				replyId: {
-					$exists: true,
-					$ne: null
-				}
-			});
-		} else {
-			push({
-				$or: [{
-					replyId: {
-						$exists: false
-					}
-				}, {
-					replyId: null
-				}]
-			});
-		}
-	}
-
-	if (renote != null) {
-		if (renote) {
-			push({
-				renoteId: {
-					$exists: true,
-					$ne: null
-				}
-			});
-		} else {
-			push({
-				$or: [{
-					renoteId: {
-						$exists: false
-					}
-				}, {
-					renoteId: null
-				}]
-			});
-		}
-	}
-
-	if (media != null) {
-		if (media) {
-			push({
-				mediaIds: {
-					$exists: true,
-					$ne: null
-				}
-			});
-		} else {
-			push({
-				$or: [{
-					mediaIds: {
-						$exists: false
-					}
-				}, {
-					mediaIds: null
-				}]
-			});
-		}
-	}
-
-	if (poll != null) {
-		if (poll) {
-			push({
-				poll: {
-					$exists: true,
-					$ne: null
-				}
-			});
-		} else {
-			push({
-				$or: [{
-					poll: {
-						$exists: false
-					}
-				}, {
-					poll: null
-				}]
-			});
-		}
-	}
-
-	if (sinceDate) {
-		push({
-			createdAt: {
-				$gt: new Date(sinceDate)
-			}
-		});
-	}
-
-	if (untilDate) {
-		push({
-			createdAt: {
-				$lt: new Date(untilDate)
-			}
-		});
-	}
-
-	if (q.$and.length == 0) {
-		q = {};
-	}
-
-	// Search notes
-	const notes = await Note
-		.find(q, {
-			sort: {
-				_id: -1
-			},
-			limit: max,
-			skip: offset
-		});
-
-	// Serialize
-	res(await Promise.all(notes.map(async note =>
-		await pack(note, me))));
-}
diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts
index 1eb4cde49..9be7cfffb 100644
--- a/src/server/api/endpoints/notes/search_by_tag.ts
+++ b/src/server/api/endpoints/notes/search_by_tag.ts
@@ -1,6 +1,6 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Mute from '../../../../models/mute';
 import { getFriendIds } from '../../common/get-friends';
 import { pack } from '../../../../models/note';
@@ -8,7 +8,7 @@ import { pack } from '../../../../models/note';
 /**
  * Search notes by tag
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'tag' parameter
 	const [tag, tagError] = $.str.get(params.tag);
 	if (tagError) return rej('invalid tag param');
@@ -69,7 +69,6 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
 
-	let includeUsers = includeUserIds;
 	if (includeUserUsernames != null) {
 		const ids = (await Promise.all(includeUserUsernames.map(async (username) => {
 			const _user = await User.findOne({
@@ -77,10 +76,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			});
 			return _user ? _user._id : null;
 		}))).filter(id => id != null);
-		includeUsers = includeUsers.concat(ids);
+
+		ids.forEach(id => includeUserIds.push(id));
 	}
 
-	let excludeUsers = excludeUserIds;
 	if (excludeUserUsernames != null) {
 		const ids = (await Promise.all(excludeUserUsernames.map(async (username) => {
 			const _user = await User.findOne({
@@ -88,24 +87,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			});
 			return _user ? _user._id : null;
 		}))).filter(id => id != null);
-		excludeUsers = excludeUsers.concat(ids);
+
+		ids.forEach(id => excludeUserIds.push(id));
 	}
 
-	search(res, rej, me, tag, includeUsers, excludeUsers, following,
-			mute, reply, renote, media, poll, sinceDate, untilDate, offset, limit);
-});
-
-async function search(
-	res, rej, me, tag, includeUserIds, excludeUserIds, following,
-	mute, reply, renote, media, poll, sinceDate, untilDate, offset, max) {
-
 	let q: any = {
 		$and: [{
 			tagsLower: tag.toLowerCase()
 		}]
 	};
 
-	const push = x => q.$and.push(x);
+	const push = (x: any) => q.$and.push(x);
 
 	if (includeUserIds && includeUserIds.length != 0) {
 		push({
@@ -320,10 +312,10 @@ async function search(
 			sort: {
 				_id: -1
 			},
-			limit: max,
+			limit: limit,
 			skip: offset
 		});
 
 	// Serialize
 	res(await Promise.all(notes.map(note => pack(note, me))));
-}
+});
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
index 78dc55a70..1ba714599 100644
--- a/src/server/api/endpoints/notes/show.ts
+++ b/src/server/api/endpoints/notes/show.ts
@@ -1,17 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note, { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Show a note
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index f1d741d5e..18c0acd37 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -1,16 +1,14 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { getFriends } from '../../common/get-friends';
 import { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get timeline of myself
  */
-module.exports = async (params, user, app) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
index 4735bec51..9c0a1bb11 100644
--- a/src/server/api/endpoints/notes/trend.ts
+++ b/src/server/api/endpoints/notes/trend.ts
@@ -1,18 +1,12 @@
-/**
- * Module dependencies
- */
 const ms = require('ms');
 import $ from 'cafy';
 import Note, { pack } from '../../../../models/note';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get trend notes
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index a74a5141f..8aa800b71 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -1,16 +1,14 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import Mute from '../../../../models/mute';
 import { pack } from '../../../../models/note';
 import UserList from '../../../../models/user-list';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * Get timeline of a user list
  */
-module.exports = async (params, user, app) => {
+module.exports = async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts
index 7a48ca3e6..faaaf65a2 100644
--- a/src/server/api/endpoints/notifications/mark_as_read_all.ts
+++ b/src/server/api/endpoints/notifications/mark_as_read_all.ts
@@ -1,11 +1,11 @@
 import Notification from '../../../../models/notification';
 import event from '../../../../publishers/stream';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 
 /**
  * Mark as read all notifications
  */
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Update documents
 	await Notification.update({
 		notifieeId: user._id,
diff --git a/src/server/api/endpoints/reversi/games.ts b/src/server/api/endpoints/reversi/games.ts
index 9d879ecf2..1455f191f 100644
--- a/src/server/api/endpoints/reversi/games.ts
+++ b/src/server/api/endpoints/reversi/games.ts
@@ -1,7 +1,8 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import ReversiGame, { pack } from '../../../../models/reversi-game';
+import { ILocalUser } from '../../../../models/user';
 
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'my' parameter
 	const [my = false, myErr] = $.bool.optional().get(params.my);
 	if (myErr) return rej('invalid my param');
diff --git a/src/server/api/endpoints/reversi/games/show.ts b/src/server/api/endpoints/reversi/games/show.ts
index f32eb2351..d70ee547a 100644
--- a/src/server/api/endpoints/reversi/games/show.ts
+++ b/src/server/api/endpoints/reversi/games/show.ts
@@ -1,8 +1,9 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import ReversiGame, { pack } from '../../../../../models/reversi-game';
 import Reversi from '../../../../../reversi/core';
+import { ILocalUser } from '../../../../../models/user';
 
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'gameId' parameter
 	const [gameId, gameIdErr] = $.type(ID).get(params.gameId);
 	if (gameIdErr) return rej('invalid gameId param');
diff --git a/src/server/api/endpoints/reversi/invitations.ts b/src/server/api/endpoints/reversi/invitations.ts
index fc487205a..d7727071a 100644
--- a/src/server/api/endpoints/reversi/invitations.ts
+++ b/src/server/api/endpoints/reversi/invitations.ts
@@ -1,6 +1,7 @@
 import Matching, { pack as packMatching } from '../../../../models/reversi-matching';
+import { ILocalUser } from '../../../../models/user';
 
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Find session
 	const invitations = await Matching.find({
 		childId: user._id
diff --git a/src/server/api/endpoints/reversi/match.ts b/src/server/api/endpoints/reversi/match.ts
index 5a699ddba..907df7cf4 100644
--- a/src/server/api/endpoints/reversi/match.ts
+++ b/src/server/api/endpoints/reversi/match.ts
@@ -1,11 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Matching, { pack as packMatching } from '../../../../models/reversi-matching';
 import ReversiGame, { pack as packGame } from '../../../../models/reversi-game';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import publishUserStream, { publishReversiStream } from '../../../../publishers/stream';
 import { eighteight } from '../../../../reversi/maps';
 
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [childId, childIdErr] = $.type(ID).get(params.userId);
 	if (childIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/reversi/match/cancel.ts b/src/server/api/endpoints/reversi/match/cancel.ts
index bc8a4cd64..1c9c799db 100644
--- a/src/server/api/endpoints/reversi/match/cancel.ts
+++ b/src/server/api/endpoints/reversi/match/cancel.ts
@@ -1,6 +1,7 @@
 import Matching from '../../../../../models/reversi-matching';
+import { ILocalUser } from '../../../../../models/user';
 
-module.exports = (params, user) => new Promise(async (res, rej) => {
+module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	await Matching.remove({
 		parentId: user._id
 	});
diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts
index b22a8b08e..f04a77fa4 100644
--- a/src/server/api/endpoints/sw/register.ts
+++ b/src/server/api/endpoints/sw/register.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import Subscription from '../../../../models/sw-subscription';
+import { ILocalUser } from '../../../../models/user';
 
 /**
  * subscribe service worker
  */
-module.exports = async (params, user, app) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'endpoint' parameter
 	const [endpoint, endpointErr] = $.str.get(params.endpoint);
 	if (endpointErr) return rej('invalid endpoint param');
diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts
index b11bec4e5..aad3adc51 100644
--- a/src/server/api/endpoints/username/available.ts
+++ b/src/server/api/endpoints/username/available.ts
@@ -1,17 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import User from '../../../../models/user';
 import { validateUsername } from '../../../../models/user';
 
 /**
  * Check available username
- *
- * @param {any} params
- * @return {Promise<any>}
  */
-module.exports = async (params) => new Promise(async (res, rej) => {
+module.exports = async (params: any) => new Promise(async (res, rej) => {
 	// Get 'username' parameter
 	const [username, usernameError] = $.str.pipe(validateUsername).get(params.username);
 	if (usernameError) return rej('invalid username param');
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index eb581cb7e..b8df6f3ec 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -1,13 +1,10 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
-import User, { pack } from '../../../models/user';
+import User, { pack, ILocalUser } from '../../../models/user';
 
 /**
  * Lists all users
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 810cd7341..53133ee96 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -1,8 +1,5 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import { pack } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
@@ -10,7 +7,7 @@ import { getFriendIds } from '../../common/get-friends';
 /**
  * Get followers of a user
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 3373b9d63..206120019 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -1,20 +1,13 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 import Following from '../../../../models/following';
 import { pack } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
 
 /**
  * Get following users of a user
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
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 64d737a06..ba8779d33 100644
--- a/src/server/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts
@@ -1,11 +1,8 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
@@ -64,7 +61,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		}
 	});
 
-	const repliedUsers = {};
+	const repliedUsers: any = {};
 
 	// Extract replies from recent notes
 	replyTargetNotes.forEach(note => {
diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts
index 100a78b87..cdd1a0d81 100644
--- a/src/server/api/endpoints/users/lists/create.ts
+++ b/src/server/api/endpoints/users/lists/create.ts
@@ -1,13 +1,11 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
 import UserList, { pack } from '../../../../../models/user-list';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Create a user list
  */
-module.exports = async (params, user) => new Promise(async (res, rej) => {
+module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'title' parameter
 	const [title, titleErr] = $.str.range(1, 100).get(params.title);
 	if (titleErr) return rej('invalid title param');
diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts
index d19339a1f..bf8391d86 100644
--- a/src/server/api/endpoints/users/lists/list.ts
+++ b/src/server/api/endpoints/users/lists/list.ts
@@ -1,9 +1,10 @@
 import UserList, { pack } from '../../../../../models/user-list';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Add a user to a user list
  */
-module.exports = async (params, me) => new Promise(async (res, rej) => {
+module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Fetch lists
 	const userLists = await UserList.find({
 		userId: me._id,
diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts
index da5a9a134..d8a3b3c9a 100644
--- a/src/server/api/endpoints/users/lists/push.ts
+++ b/src/server/api/endpoints/users/lists/push.ts
@@ -1,6 +1,6 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import UserList from '../../../../../models/user-list';
-import User, { pack as packUser, isRemoteUser, getGhost } from '../../../../../models/user';
+import User, { pack as packUser, isRemoteUser, getGhost, ILocalUser } from '../../../../../models/user';
 import { publishUserListStream } from '../../../../../publishers/stream';
 import ap from '../../../../../remote/activitypub/renderer';
 import renderFollow from '../../../../../remote/activitypub/renderer/follow';
@@ -9,7 +9,7 @@ import { deliver } from '../../../../../queue';
 /**
  * Add a user to a user list
  */
-module.exports = async (params, me) => new Promise(async (res, rej) => {
+module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'listId' parameter
 	const [listId, listIdErr] = $.type(ID).get(params.listId);
 	if (listIdErr) return rej('invalid listId param');
diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts
index 16cb3382f..e4ae23961 100644
--- a/src/server/api/endpoints/users/lists/show.ts
+++ b/src/server/api/endpoints/users/lists/show.ts
@@ -1,10 +1,11 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
 import UserList, { pack } from '../../../../../models/user-list';
+import { ILocalUser } from '../../../../../models/user';
 
 /**
  * Show a user list
  */
-module.exports = async (params, me) => new Promise(async (res, rej) => {
+module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'listId' parameter
 	const [listId, listIdErr] = $.type(ID).get(params.listId);
 	if (listIdErr) return rej('invalid listId param');
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 061c363d0..222a8d950 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -1,15 +1,12 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
 import getHostLower from '../../common/get-host-lower';
 import Note, { pack } from '../../../../models/note';
-import User from '../../../../models/user';
+import User, { ILocalUser } from '../../../../models/user';
 
 /**
  * Get notes of a user
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).optional().get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 23821a552..1d0d889f1 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -1,20 +1,13 @@
-/**
- * Module dependencies
- */
 const ms = require('ms');
 import $ from 'cafy';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 import { getFriendIds } from '../../common/get-friends';
 import Mute from '../../../../models/mute';
 
 /**
  * Get recommended users
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+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);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index 95b9e4f4b..e29c8d32f 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -1,40 +1,19 @@
-/**
- * Module dependencies
- */
-import * as mongo from 'mongodb';
 import $ from 'cafy';
-import User, { pack } from '../../../../models/user';
-import config from '../../../../config';
+import User, { pack, ILocalUser } from '../../../../models/user';
 const escapeRegexp = require('escape-regexp');
 
 /**
  * Search a user
- *
- * @param {any} params
- * @param {any} me
- * @return {Promise<any>}
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'query' parameter
 	const [query, queryError] = $.str.pipe(x => x != '').get(params.query);
 	if (queryError) return rej('invalid query param');
 
-	// Get 'offset' parameter
-	const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset);
-	if (offsetErr) return rej('invalid offset param');
-
 	// Get 'max' parameter
 	const [max = 10, maxErr] = $.num.optional().range(1, 30).get(params.max);
 	if (maxErr) return rej('invalid max param');
 
-	// If Elasticsearch is available, search by $
-	// If not, search by MongoDB
-	(config.elasticsearch.enable ? byElasticsearch : byNative)
-		(res, rej, me, query, offset, max);
-});
-
-// Search by MongoDB
-async function byNative(res, rej, me, query, offset, max) {
 	const escapedQuery = escapeRegexp(query);
 
 	// Search users
@@ -51,49 +30,5 @@ async function byNative(res, rej, me, query, offset, max) {
 		});
 
 	// Serialize
-	res(await Promise.all(users.map(async user =>
-		await pack(user, me, { detail: true }))));
-}
-
-// Search by Elasticsearch
-async function byElasticsearch(res, rej, me, query, offset, max) {
-	const es = require('../../db/elasticsearch');
-
-	es.search({
-		index: 'misskey',
-		type: 'user',
-		body: {
-			size: max,
-			from: offset,
-			query: {
-				simple_query_string: {
-					fields: ['username', 'name', 'bio'],
-					query: query,
-					default_operator: 'and'
-				}
-			}
-		}
-	}, async (error, response) => {
-		if (error) {
-			console.error(error);
-			return res(500);
-		}
-
-		if (response.hits.total === 0) {
-			return res([]);
-		}
-
-		const hits = response.hits.hits.map(hit => new mongo.ObjectID(hit._id));
-
-		const users = await User
-			.find({
-				_id: {
-					$in: hits
-				}
-			});
-
-		// Serialize
-		res(await Promise.all(users.map(async user =>
-			await pack(user, me, { detail: true }))));
-	});
-}
+	res(await Promise.all(users.map(user => pack(user, me, { detail: true }))));
+});
diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts
index 7c9fbba0f..937f9af58 100644
--- a/src/server/api/endpoints/users/search_by_username.ts
+++ b/src/server/api/endpoints/users/search_by_username.ts
@@ -1,13 +1,10 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 
 /**
  * Search a user by username
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'query' parameter
 	const [query, queryError] = $.str.get(params.query);
 	if (queryError) return rej('invalid query param');
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index b8c6ff25c..bf7e2a231 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -1,8 +1,5 @@
-/**
- * Module dependencies
- */
 import $ from 'cafy'; import ID from '../../../../cafy-id';
-import User, { pack } from '../../../../models/user';
+import User, { pack, ILocalUser } from '../../../../models/user';
 import resolveRemoteUser from '../../../../remote/resolve-user';
 
 const cursorOption = { fields: { data: false } };
@@ -10,7 +7,7 @@ const cursorOption = { fields: { data: false } };
 /**
  * Show user(s)
  */
-module.exports = (params, me) => new Promise(async (res, rej) => {
+module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	let user;
 
 	// Get 'userId' parameter
@@ -49,7 +46,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 				return rej('failed to resolve remote user');
 			}
 		} else {
-			const q = userId !== undefined
+			const q: any = userId !== undefined
 				? { _id: userId }
 				: { usernameLower: username.toLowerCase(), host: null };
 
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index fee899b37..cb47d400b 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -1,7 +1,7 @@
 import * as Koa from 'koa';
 import * as bcrypt from 'bcryptjs';
 import { generate as generateKeypair } from '../../../crypto_key';
-import recaptcha = require('recaptcha-promise');
+const recaptcha = require('recaptcha-promise');
 import User, { IUser, validateUsername, validatePassword, pack } from '../../../models/user';
 import generateUserToken from '../common/generate-native-user-token';
 import config from '../../../config';
diff --git a/src/server/api/service/github.ts b/src/server/api/service/github.ts
index da33648a1..9024740a9 100644
--- a/src/server/api/service/github.ts
+++ b/src/server/api/service/github.ts
@@ -11,7 +11,7 @@ const handler = new EventEmitter();
 
 let bot: IUser;
 
-const post = async text => {
+const post = async (text: string) => {
 	if (bot == null) {
 		const account = await User.findOne({
 			usernameLower: config.github_bot.username.toLowerCase()
@@ -90,7 +90,7 @@ handler.on('push', event => {
 		case 'refs/heads/master':
 			const pusher = event.pusher;
 			const compare = event.compare;
-			const commits = event.commits;
+			const commits: any[] = event.commits;
 			post([
 				`Pushed by **${pusher.name}** with ?[${commits.length} commit${commits.length > 1 ? 's' : ''}](${compare}):`,
 				commits.reverse().map(commit => `・[?[${commit.id.substr(0, 7)}](${commit.url})] ${commit.message.split('\n')[0]}`).join('\n'),
diff --git a/src/server/api/stream/notes-stats.ts b/src/server/api/stream/notes-stats.ts
index 739b32584..ab0062001 100644
--- a/src/server/api/stream/notes-stats.ts
+++ b/src/server/api/stream/notes-stats.ts
@@ -4,7 +4,7 @@ import Xev from 'xev';
 const ev = new Xev();
 
 export default function(request: websocket.request, connection: websocket.connection): void {
-	const onStats = stats => {
+	const onStats = (stats: any) => {
 		connection.send(JSON.stringify({
 			type: 'stats',
 			body: stats
diff --git a/src/server/api/stream/requests.ts b/src/server/api/stream/requests.ts
deleted file mode 100644
index d7bb5e6c5..000000000
--- a/src/server/api/stream/requests.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as websocket from 'websocket';
-import Xev from 'xev';
-
-const ev = new Xev();
-
-export default function(request: websocket.request, connection: websocket.connection): void {
-	const onRequest = request => {
-		connection.send(JSON.stringify({
-			type: 'request',
-			body: request
-		}));
-	};
-
-	ev.addListener('request', onRequest);
-
-	connection.on('close', () => {
-		ev.removeListener('request', onRequest);
-	});
-}
diff --git a/src/server/api/stream/reversi-game.ts b/src/server/api/stream/reversi-game.ts
index 63d9b220b..ea8a9741d 100644
--- a/src/server/api/stream/reversi-game.ts
+++ b/src/server/api/stream/reversi-game.ts
@@ -61,7 +61,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		}
 	});
 
-	async function updateSettings(settings) {
+	async function updateSettings(settings: any) {
 		const game = await ReversiGame.findOne({ _id: gameId });
 
 		if (game.isStarted) return;
@@ -78,7 +78,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		publishReversiGameStream(gameId, 'update-settings', settings);
 	}
 
-	async function initForm(form) {
+	async function initForm(form: any) {
 		const game = await ReversiGame.findOne({ _id: gameId });
 
 		if (game.isStarted) return;
@@ -100,7 +100,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		});
 	}
 
-	async function updateForm(id, value) {
+	async function updateForm(id: string, value: any) {
 		const game = await ReversiGame.findOne({ _id: gameId });
 
 		if (game.isStarted) return;
@@ -108,7 +108,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 		const form = game.user1Id.equals(user._id) ? game.form2 : game.form1;
 
-		const item = form.find(i => i.id == id);
+		const item = form.find((i: any) => i.id == id);
 
 		if (item == null) return;
 
@@ -131,7 +131,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		});
 	}
 
-	async function message(message) {
+	async function message(message: any) {
 		message.id = Math.random();
 		publishReversiGameStream(gameId, 'message', {
 			userId: user._id,
@@ -246,7 +246,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	}
 
 	// 石を打つ
-	async function set(pos) {
+	async function set(pos: number) {
 		const game = await ReversiGame.findOne({ _id: gameId });
 
 		if (!game.isStarted) return;
@@ -315,7 +315,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		}
 	}
 
-	async function check(crc32) {
+	async function check(crc32: string) {
 		const game = await ReversiGame.findOne({ _id: gameId });
 
 		if (!game.isStarted) return;
diff --git a/src/server/api/stream/server-stats.ts b/src/server/api/stream/server-stats.ts
index 342170a21..2a058de6c 100644
--- a/src/server/api/stream/server-stats.ts
+++ b/src/server/api/stream/server-stats.ts
@@ -4,7 +4,7 @@ import Xev from 'xev';
 const ev = new Xev();
 
 export default function(request: websocket.request, connection: websocket.connection): void {
-	const onStats = stats => {
+	const onStats = (stats: any) => {
 		connection.send(JSON.stringify({
 			type: 'stats',
 			body: stats
diff --git a/src/server/api/streaming.ts b/src/server/api/streaming.ts
index a3e4ed6f8..81adff0b5 100644
--- a/src/server/api/streaming.ts
+++ b/src/server/api/streaming.ts
@@ -14,7 +14,6 @@ import reversiGameStream from './stream/reversi-game';
 import reversiStream from './stream/reversi';
 import serverStatsStream from './stream/server-stats';
 import notesStatsStream from './stream/notes-stats';
-import requestsStream from './stream/requests';
 import { ParsedUrlQuery } from 'querystring';
 import authenticate from './authenticate';
 
@@ -39,11 +38,6 @@ module.exports = (server: http.Server) => {
 			return;
 		}
 
-		if (request.resourceURL.pathname === '/requests') {
-			requestsStream(request, connection);
-			return;
-		}
-
 		// Connect to Redis
 		const subscriber = redis.createClient(
 			config.redis.port, config.redis.host);
diff --git a/src/server/index.ts b/src/server/index.ts
index fc3d252e1..f1fcf58c8 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -62,7 +62,7 @@ app.use(mount(require('./web')));
 
 function createServer() {
 	if (config.https) {
-		const certs = {};
+		const certs: any = {};
 		Object.keys(config.https).forEach(k => {
 			certs[k] = fs.readFileSync(config.https[k]);
 		});
diff --git a/webpack.config.ts b/webpack.config.ts
index 480f5d4a7..3c426ebb4 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -6,7 +6,7 @@ import * as fs from 'fs';
 import * as webpack from 'webpack';
 import chalk from 'chalk';
 const { VueLoaderPlugin } = require('vue-loader');
-import jsonImporter from 'node-sass-json-importer';
+const jsonImporter = require('node-sass-json-importer');
 const minifyHtml = require('html-minifier').minify;
 const WebpackOnBuildPlugin = require('on-build-webpack');
 //const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
@@ -24,10 +24,17 @@ const meta = require('./package.json');
 const version = meta.clientVersion;
 const codename = meta.codename;
 
+declare var global: {
+	faReplacement: typeof faReplacement;
+	collapseSpacesReplacement: any;
+	base64replacement: any;
+	i18nReplacement: typeof i18nReplacement;
+};
+
 //#region Replacer definitions
 global['faReplacement'] = faReplacement;
 
-global['collapseSpacesReplacement'] = html => {
+global['collapseSpacesReplacement'] = (html: string) => {
 	return minifyHtml(html, {
 		collapseWhitespace: true,
 		collapseInlineTagWhitespace: true,
@@ -35,7 +42,7 @@ global['collapseSpacesReplacement'] = html => {
 	}).replace(/\t/g, '');
 };
 
-global['base64replacement'] = (_, key) => {
+global['base64replacement'] = (_: any, key: string) => {
 	return fs.readFileSync(__dirname + '/src/client/' + key, 'base64');
 };
 
@@ -89,10 +96,10 @@ const consts = {
 	_WELCOME_BG_URL_: config.welcome_bg_url
 };
 
-const _consts = {};
+const _consts: { [ key: string ]: any } = {};
 
 Object.keys(consts).forEach(key => {
-	_consts[key] = JSON.stringify(consts[key]);
+	_consts[key] = JSON.stringify((consts as any)[key]);
 });
 //#endregion
 
@@ -106,7 +113,7 @@ const plugins = [
 	new webpack.DefinePlugin({
 		'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')
 	}),
-	new WebpackOnBuildPlugin(stats => {
+	new WebpackOnBuildPlugin((stats: any) => {
 		fs.writeFileSync('./built/client/meta.json', JSON.stringify({
 			version
 		}), 'utf-8');
diff --git a/webpack/i18n.ts b/webpack/i18n.ts
index e2cce060e..f73af7258 100644
--- a/webpack/i18n.ts
+++ b/webpack/i18n.ts
@@ -4,7 +4,7 @@
 
 export const pattern = /%i18n:([a-z0-9_\-@\.]+?)%/g;
 
-export const replacement = (ctx, match, key) => {
+export const replacement = (ctx: any, _: any, key: string) => {
 	const client = '/src/client/app/';
 	let name = null;