From 0cc5ca598a6ca5b3ac105419e905cb89df854698 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 09:10:05 +0900
Subject: [PATCH 01/43] wip

---
 src/api/models/access-token.ts      | 18 +++++--
 src/api/models/app.ts               | 20 ++++---
 src/api/models/appdata.ts           |  3 --
 src/api/models/auth-session.ts      |  9 ++--
 src/api/models/channel-watching.ts  | 13 ++++-
 src/api/models/channel.ts           | 11 ++--
 src/api/models/drive-file.ts        | 14 ++---
 src/api/models/drive-folder.ts      | 14 ++---
 src/api/models/drive-tag.ts         |  3 --
 src/api/models/favorite.ts          | 11 +++-
 src/api/models/following.ts         | 12 ++++-
 tools/migration/shell.camel-case.js | 81 +++++++++++++++++++++++++++++
 12 files changed, 166 insertions(+), 43 deletions(-)
 delete mode 100644 src/api/models/appdata.ts
 delete mode 100644 src/api/models/drive-tag.ts
 create mode 100644 tools/migration/shell.camel-case.js

diff --git a/src/api/models/access-token.ts b/src/api/models/access-token.ts
index 9985be5013..9e1cb6474a 100644
--- a/src/api/models/access-token.ts
+++ b/src/api/models/access-token.ts
@@ -1,8 +1,16 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-const collection = db.get('access_tokens');
+const AccessToken = db.get<IAccessTokens>('accessTokens');
+AccessToken.createIndex('token');
+AccessToken.createIndex('hash');
+export default AccessToken;
 
-(collection as any).createIndex('token'); // fuck type definition
-(collection as any).createIndex('hash'); // fuck type definition
-
-export default collection as any; // fuck type definition
+export type IAccessTokens = {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	appId: mongo.ObjectID;
+	userId: mongo.ObjectID;
+	token: string;
+	hash: string;
+};
diff --git a/src/api/models/app.ts b/src/api/models/app.ts
index 34e9867db7..20af049b27 100644
--- a/src/api/models/app.ts
+++ b/src/api/models/app.ts
@@ -5,16 +5,22 @@ import db from '../../db/mongodb';
 import config from '../../conf';
 
 const App = db.get<IApp>('apps');
-App.createIndex('name_id');
-App.createIndex('name_id_lower');
+App.createIndex('nameId');
+App.createIndex('nameIdLower');
 App.createIndex('secret');
 export default App;
 
 export type IApp = {
 	_id: mongo.ObjectID;
-	created_at: Date;
-	user_id: mongo.ObjectID;
+	createdAt: Date;
+	userId: mongo.ObjectID;
 	secret: string;
+	name: string;
+	nameId: string;
+	nameIdLower: string;
+	description: string;
+	permission: string;
+	callbackUrl: string;
 };
 
 export function isValidNameId(nameId: string): boolean {
@@ -70,7 +76,7 @@ export const pack = (
 	_app.id = _app._id;
 	delete _app._id;
 
-	delete _app.name_id_lower;
+	delete _app.nameIdLower;
 
 	// Visible by only owner
 	if (!opts.includeSecret) {
@@ -84,8 +90,8 @@ export const pack = (
 	if (me) {
 		// 既に連携しているか
 		const exist = await AccessToken.count({
-			app_id: _app.id,
-			user_id: me,
+			appId: _app.id,
+			userId: me,
 		}, {
 				limit: 1
 			});
diff --git a/src/api/models/appdata.ts b/src/api/models/appdata.ts
deleted file mode 100644
index 3e68354fa4..0000000000
--- a/src/api/models/appdata.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import db from '../../db/mongodb';
-
-export default db.get('appdata') as any; // fuck type definition
diff --git a/src/api/models/auth-session.ts b/src/api/models/auth-session.ts
index 997ec61c20..e6b8b2318e 100644
--- a/src/api/models/auth-session.ts
+++ b/src/api/models/auth-session.ts
@@ -3,11 +3,15 @@ import deepcopy = require('deepcopy');
 import db from '../../db/mongodb';
 import { pack as packApp } from './app';
 
-const AuthSession = db.get('auth_sessions');
+const AuthSession = db.get<IAuthSession>('authSessions');
 export default AuthSession;
 
 export interface IAuthSession {
 	_id: mongo.ObjectID;
+	createdAt: Date;
+	appId: mongo.ObjectID;
+	userId: mongo.ObjectID;
+	token: string;
 }
 
 /**
@@ -24,7 +28,6 @@ export const pack = (
 	let _session: any;
 
 	// TODO: Populate session if it ID
-
 	_session = deepcopy(session);
 
 	// Me
@@ -39,7 +42,7 @@ export const pack = (
 	delete _session._id;
 
 	// Populate app
-	_session.app = await packApp(_session.app_id, me);
+	_session.app = await packApp(_session.appId, me);
 
 	resolve(_session);
 });
diff --git a/src/api/models/channel-watching.ts b/src/api/models/channel-watching.ts
index 6184ae408d..23886d0c76 100644
--- a/src/api/models/channel-watching.ts
+++ b/src/api/models/channel-watching.ts
@@ -1,3 +1,14 @@
+import * as mongo from 'mongodb';
+
 import db from '../../db/mongodb';
 
-export default db.get('channel_watching') as any; // fuck type definition
+const ChannelWatching = db.get<IChannelWatching>('channelWatching');
+export default ChannelWatching;
+
+export interface IChannelWatching {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	deletedAt: Date;
+	channel_id: mongo.ObjectID;
+	userId: mongo.ObjectID;
+}
diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts
index 815d53593c..a753a4ebad 100644
--- a/src/api/models/channel.ts
+++ b/src/api/models/channel.ts
@@ -9,10 +9,11 @@ export default Channel;
 
 export type IChannel = {
 	_id: mongo.ObjectID;
-	created_at: Date;
+	createdAt: Date;
 	title: string;
-	user_id: mongo.ObjectID;
+	userId: mongo.ObjectID;
 	index: number;
+	watchingCount: number;
 };
 
 /**
@@ -47,7 +48,7 @@ export const pack = (
 	delete _channel._id;
 
 	// Remove needless properties
-	delete _channel.user_id;
+	delete _channel.userId;
 
 	// Me
 	const meId: mongo.ObjectID = me
@@ -61,9 +62,9 @@ export const pack = (
 	if (me) {
 		//#region Watchしているかどうか
 		const watch = await Watching.findOne({
-			user_id: meId,
+			userId: meId,
 			channel_id: _channel.id,
-			deleted_at: { $exists: false }
+			deletedAt: { $exists: false }
 		});
 
 		_channel.is_watching = watch !== null;
diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts
index 2a46d8dc4d..b0e4d1db0c 100644
--- a/src/api/models/drive-file.ts
+++ b/src/api/models/drive-file.ts
@@ -4,14 +4,14 @@ import { pack as packFolder } from './drive-folder';
 import config from '../../conf';
 import monkDb, { nativeDbConn } from '../../db/mongodb';
 
-const DriveFile = monkDb.get<IDriveFile>('drive_files.files');
+const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
 
 export default DriveFile;
 
 const getGridFSBucket = async (): Promise<mongodb.GridFSBucket> => {
 	const db = await nativeDbConn();
 	const bucket = new mongodb.GridFSBucket(db, {
-		bucketName: 'drive_files'
+		bucketName: 'driveFiles'
 	});
 	return bucket;
 };
@@ -26,8 +26,8 @@ export type IDriveFile = {
 	contentType: string;
 	metadata: {
 		properties: any;
-		user_id: mongodb.ObjectID;
-		folder_id: mongodb.ObjectID;
+		userId: mongodb.ObjectID;
+		folderId: mongodb.ObjectID;
 	}
 };
 
@@ -79,7 +79,7 @@ export const pack = (
 	let _target: any = {};
 
 	_target.id = _file._id;
-	_target.created_at = _file.uploadDate;
+	_target.createdAt = _file.uploadDate;
 	_target.name = _file.filename;
 	_target.type = _file.contentType;
 	_target.datasize = _file.length;
@@ -92,9 +92,9 @@ export const pack = (
 	if (_target.properties == null) _target.properties = {};
 
 	if (opts.detail) {
-		if (_target.folder_id) {
+		if (_target.folderId) {
 			// Populate folder
-			_target.folder = await packFolder(_target.folder_id, {
+			_target.folder = await packFolder(_target.folderId, {
 				detail: true
 			});
 		}
diff --git a/src/api/models/drive-folder.ts b/src/api/models/drive-folder.ts
index 54b45049b9..52f784e069 100644
--- a/src/api/models/drive-folder.ts
+++ b/src/api/models/drive-folder.ts
@@ -8,10 +8,10 @@ export default DriveFolder;
 
 export type IDriveFolder = {
 	_id: mongo.ObjectID;
-	created_at: Date;
+	createdAt: Date;
 	name: string;
-	user_id: mongo.ObjectID;
-	parent_id: mongo.ObjectID;
+	userId: mongo.ObjectID;
+	parentId: mongo.ObjectID;
 };
 
 export function isValidFolderName(name: string): boolean {
@@ -55,20 +55,20 @@ export const pack = (
 
 	if (opts.detail) {
 		const childFoldersCount = await DriveFolder.count({
-			parent_id: _folder.id
+			parentId: _folder.id
 		});
 
 		const childFilesCount = await DriveFile.count({
-			'metadata.folder_id': _folder.id
+			'metadata.folderId': _folder.id
 		});
 
 		_folder.folders_count = childFoldersCount;
 		_folder.files_count = childFilesCount;
 	}
 
-	if (opts.detail && _folder.parent_id) {
+	if (opts.detail && _folder.parentId) {
 		// Populate parent folder
-		_folder.parent = await pack(_folder.parent_id, {
+		_folder.parent = await pack(_folder.parentId, {
 			detail: true
 		});
 	}
diff --git a/src/api/models/drive-tag.ts b/src/api/models/drive-tag.ts
deleted file mode 100644
index 991c935e81..0000000000
--- a/src/api/models/drive-tag.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import db from '../../db/mongodb';
-
-export default db.get('drive_tags') as any; // fuck type definition
diff --git a/src/api/models/favorite.ts b/src/api/models/favorite.ts
index e01d9e343c..5ba55c4c9f 100644
--- a/src/api/models/favorite.ts
+++ b/src/api/models/favorite.ts
@@ -1,3 +1,12 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('favorites') as any; // fuck type definition
+const Favorites = db.get<IFavorites>('favorites');
+export default Favorites;
+
+export type IFavorites = {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	userId: mongo.ObjectID;
+	postId: mongo.ObjectID;
+};
diff --git a/src/api/models/following.ts b/src/api/models/following.ts
index cb3db9b539..1163bf6b38 100644
--- a/src/api/models/following.ts
+++ b/src/api/models/following.ts
@@ -1,3 +1,13 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('following') as any; // fuck type definition
+const Following = db.get<IFollowing>('following');
+export default Following;
+
+export type IFollowing = {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	deletedAt: Date;
+	followeeId: mongo.ObjectID;
+	followerId: mongo.ObjectID;
+};
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
new file mode 100644
index 0000000000..6d6b01a071
--- /dev/null
+++ b/tools/migration/shell.camel-case.js
@@ -0,0 +1,81 @@
+db.access_tokens.renameCollection('accessTokens');
+db.accessTokens.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		app_id: 'appId',
+		user_id: 'userId',
+	}
+}, false, true);
+
+db.apps.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		name_id: 'nameId',
+		name_id_lower: 'nameIdLower',
+		callback_url: 'callbackUrl',
+	}
+}, false, true);
+
+db.auth_sessions.renameCollection('authSessions');
+db.authSessions.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		app_id: 'appId',
+		user_id: 'userId',
+	}
+}, false, true);
+
+db.channel_watching.renameCollection('channelWatching');
+db.channelWatching.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		deleted_at: 'deletedAt',
+		channel_id: 'channelId',
+		user_id: 'userId',
+	}
+}, false, true);
+
+db.channels.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		watching_count: 'watchingCount'
+	}
+}, false, true);
+
+db.drive_files.files.renameCollection('driveFiles.files');
+db.drive_files.chunks.renameCollection('driveFiles.chunks');
+db.driveFiles.files.update({}, {
+	$rename: {
+		'metadata.user_id': 'metadata.userId',
+		'metadata.folder_id': 'metadata.folderId',
+		'metadata.properties.average_color': 'metadata.properties.avgColor'
+	}
+}, false, true);
+
+db.drive_folders.renameCollection('driveFolders');
+db.driveFolders.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		parent_id: 'parentId',
+	}
+}, false, true);
+
+db.favorites.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		post_id: 'postId',
+	}
+}, false, true);
+
+db.following.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		deleted_at: 'deletedAt',
+		followee_id: 'followeeId',
+		follower_id: 'followerId',
+	}
+}, false, true);

From 10d828c94f5c4fd00a2cb1896f10537ce19256c6 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 09:15:58 +0900
Subject: [PATCH 02/43] Update dependencies :rocket:

---
 package.json | 46 +++++++++++++++++++++++-----------------------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/package.json b/package.json
index d9ed80b470..4e3da7d0b3 100644
--- a/package.json
+++ b/package.json
@@ -44,11 +44,11 @@
 		"@types/express": "4.11.1",
 		"@types/gm": "1.17.33",
 		"@types/gulp": "3.8.36",
-		"@types/gulp-htmlmin": "1.3.31",
-		"@types/gulp-mocha": "0.0.31",
+		"@types/gulp-htmlmin": "1.3.32",
+		"@types/gulp-mocha": "0.0.32",
 		"@types/gulp-rename": "0.0.33",
 		"@types/gulp-replace": "0.0.31",
-		"@types/gulp-uglify": "3.0.4",
+		"@types/gulp-uglify": "3.0.5",
 		"@types/gulp-util": "3.0.34",
 		"@types/inquirer": "0.0.38",
 		"@types/is-root": "1.0.0",
@@ -56,13 +56,13 @@
 		"@types/js-yaml": "3.10.1",
 		"@types/license-checker": "15.0.0",
 		"@types/mkdirp": "0.5.2",
-		"@types/mocha": "2.2.48",
-		"@types/mongodb": "3.0.8",
+		"@types/mocha": "5.0.0",
+		"@types/mongodb": "3.0.9",
 		"@types/monk": "6.0.0",
 		"@types/morgan": "1.7.35",
 		"@types/ms": "0.7.30",
 		"@types/multer": "1.3.6",
-		"@types/node": "9.4.7",
+		"@types/node": "9.6.0",
 		"@types/proxy-addr": "2.0.0",
 		"@types/pug": "2.0.4",
 		"@types/qrcode": "0.8.1",
@@ -76,13 +76,13 @@
 		"@types/speakeasy": "2.0.2",
 		"@types/tmp": "0.0.33",
 		"@types/uuid": "3.4.3",
-		"@types/webpack": "4.1.1",
+		"@types/webpack": "4.1.2",
 		"@types/webpack-stream": "3.2.10",
 		"@types/websocket": "0.0.38",
 		"@types/ws": "4.0.1",
 		"accesses": "2.5.0",
 		"animejs": "2.2.0",
-		"autosize": "4.0.0",
+		"autosize": "4.0.1",
 		"autwh": "0.0.1",
 		"bcryptjs": "2.4.3",
 		"body-parser": "1.18.2",
@@ -114,7 +114,7 @@
 		"fuckadblock": "3.2.1",
 		"gm": "1.23.1",
 		"gulp": "3.9.1",
-		"gulp-cssnano": "2.1.2",
+		"gulp-cssnano": "2.1.3",
 		"gulp-htmlmin": "4.0.0",
 		"gulp-imagemin": "4.1.0",
 		"gulp-mocha": "5.0.0",
@@ -130,25 +130,25 @@
 		"hard-source-webpack-plugin": "0.6.4",
 		"highlight.js": "9.12.0",
 		"html-minifier": "3.5.12",
-		"inquirer": "5.1.0",
+		"inquirer": "5.2.0",
 		"is-root": "2.0.0",
-		"is-url": "1.2.3",
+		"is-url": "1.2.4",
 		"js-yaml": "3.11.0",
-		"jsdom": "^11.6.2",
+		"jsdom": "11.6.2",
 		"license-checker": "18.0.0",
 		"loader-utils": "1.1.0",
 		"mecab-async": "0.1.2",
 		"mkdirp": "0.5.1",
-		"mocha": "5.0.4",
+		"mocha": "5.0.5",
 		"moji": "0.5.1",
-		"mongodb": "3.0.4",
+		"mongodb": "3.0.5",
 		"monk": "6.0.5",
 		"morgan": "1.9.0",
 		"ms": "2.1.1",
 		"multer": "1.3.0",
-		"nan": "^2.10.0",
-		"node-sass": "4.7.2",
-		"node-sass-json-importer": "3.1.5",
+		"nan": "2.10.0",
+		"node-sass": "4.8.3",
+		"node-sass-json-importer": "3.1.6",
 		"nprogress": "0.2.0",
 		"object-assign-deep": "0.3.1",
 		"on-build-webpack": "0.1.0",
@@ -157,7 +157,7 @@
 		"prominence": "0.2.0",
 		"proxy-addr": "2.0.3",
 		"pug": "2.0.3",
-		"punycode": "^2.1.0",
+		"punycode": "2.1.0",
 		"qrcode": "1.2.0",
 		"ratelimiter": "3.0.3",
 		"recaptcha-promise": "0.1.3",
@@ -181,10 +181,10 @@
 		"tcp-port-used": "0.1.2",
 		"textarea-caret": "3.1.0",
 		"tmp": "0.0.33",
-		"ts-loader": "4.0.1",
+		"ts-loader": "4.1.0",
 		"ts-node": "5.0.1",
 		"tslint": "5.9.1",
-		"typescript": "2.7.2",
+		"typescript": "2.8.1",
 		"typescript-eslint-parser": "14.0.0",
 		"uglify-es": "3.3.9",
 		"url-loader": "1.0.1",
@@ -195,13 +195,13 @@
 		"vue-cropperjs": "2.2.0",
 		"vue-js-modal": "1.3.12",
 		"vue-json-tree-view": "2.1.3",
-		"vue-loader": "14.2.1",
+		"vue-loader": "14.2.2",
 		"vue-router": "3.0.1",
 		"vue-template-compiler": "2.5.16",
 		"vuedraggable": "2.16.0",
 		"web-push": "3.3.0",
-		"webfinger.js": "^2.6.6",
-		"webpack": "4.2.0",
+		"webfinger.js": "2.6.6",
+		"webpack": "4.3.0",
 		"webpack-cli": "2.0.13",
 		"webpack-replace-loader": "1.3.0",
 		"websocket": "1.0.25",

From 16f2adf48c39a257b6c6eebc54ed36878987d7bd Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 09:27:57 +0900
Subject: [PATCH 03/43] Prepare new codename

---
 package.json                                 | 1 +
 src/index.ts                                 | 1 -
 src/web/app/common/views/widgets/version.vue | 7 ++++---
 src/web/app/config.ts                        | 4 ++--
 src/web/app/init.ts                          | 4 ++--
 src/web/app/mobile/views/pages/settings.vue  | 7 ++++---
 swagger.js                                   | 6 +++---
 webpack.config.ts                            | 3 ++-
 8 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/package.json b/package.json
index 4e3da7d0b3..3f9e497389 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
 	"name": "misskey",
 	"author": "syuilo <i@syuilo.com>",
 	"version": "0.0.4224",
+	"codename": "nighthike",
 	"license": "MIT",
 	"description": "A miniblog-based SNS",
 	"bugs": "https://github.com/syuilo/misskey/issues",
diff --git a/src/index.ts b/src/index.ts
index 218455d6f4..a8181acda2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -89,7 +89,6 @@ function workerMain() {
  */
 async function init(): Promise<Config> {
 	Logger.info('Welcome to Misskey!');
-	Logger.info(chalk.bold('Misskey <aoi>'));
 	Logger.info('Initializing...');
 
 	EnvironmentInfo.show();
diff --git a/src/web/app/common/views/widgets/version.vue b/src/web/app/common/views/widgets/version.vue
index 5072d9b74a..30b632b396 100644
--- a/src/web/app/common/views/widgets/version.vue
+++ b/src/web/app/common/views/widgets/version.vue
@@ -1,16 +1,17 @@
 <template>
-<p>ver {{ v }} (葵 aoi)</p>
+<p>ver {{ version }} ({{ codename }})</p>
 </template>
 
 <script lang="ts">
-import { version } from '../../../config';
+import { version, codename } from '../../../config';
 import define from '../../../common/define-widget';
 export default define({
 	name: 'version'
 }).extend({
 	data() {
 		return {
-			v: version
+			version,
+			codename
 		};
 	}
 });
diff --git a/src/web/app/config.ts b/src/web/app/config.ts
index 8ea6f70101..522d7ff056 100644
--- a/src/web/app/config.ts
+++ b/src/web/app/config.ts
@@ -7,13 +7,13 @@ declare const _DOCS_URL_: string;
 declare const _STATS_URL_: string;
 declare const _STATUS_URL_: string;
 declare const _DEV_URL_: string;
-declare const _CH_URL_: string;
 declare const _LANG_: string;
 declare const _RECAPTCHA_SITEKEY_: string;
 declare const _SW_PUBLICKEY_: string;
 declare const _THEME_COLOR_: string;
 declare const _COPYRIGHT_: string;
 declare const _VERSION_: string;
+declare const _CODENAME_: string;
 declare const _LICENSE_: string;
 declare const _GOOGLE_MAPS_API_KEY_: string;
 
@@ -26,12 +26,12 @@ export const docsUrl = _DOCS_URL_;
 export const statsUrl = _STATS_URL_;
 export const statusUrl = _STATUS_URL_;
 export const devUrl = _DEV_URL_;
-export const chUrl = _CH_URL_;
 export const lang = _LANG_;
 export const recaptchaSitekey = _RECAPTCHA_SITEKEY_;
 export const swPublickey = _SW_PUBLICKEY_;
 export const themeColor = _THEME_COLOR_;
 export const copyright = _COPYRIGHT_;
 export const version = _VERSION_;
+export const codename = _CODENAME_;
 export const license = _LICENSE_;
 export const googleMapsApiKey = _GOOGLE_MAPS_API_KEY_;
diff --git a/src/web/app/init.ts b/src/web/app/init.ts
index 521dade866..3e5c38961f 100644
--- a/src/web/app/init.ts
+++ b/src/web/app/init.ts
@@ -14,7 +14,7 @@ import ElementLocaleJa from 'element-ui/lib/locale/lang/ja';
 import App from './app.vue';
 import checkForUpdate from './common/scripts/check-for-update';
 import MiOS, { API } from './common/mios';
-import { version, hostname, lang } from './config';
+import { version, codename, hostname, lang } from './config';
 
 let elementLocale;
 switch (lang) {
@@ -51,7 +51,7 @@ Vue.mixin({
  * APP ENTRY POINT!
  */
 
-console.info(`Misskey v${version} (葵 aoi)`);
+console.info(`Misskey v${version} (${codename})`);
 console.info(
 	'%cここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。',
 	'color: red; background: yellow; font-size: 16px; font-weight: bold;');
diff --git a/src/web/app/mobile/views/pages/settings.vue b/src/web/app/mobile/views/pages/settings.vue
index 3250999e12..a945a21c5c 100644
--- a/src/web/app/mobile/views/pages/settings.vue
+++ b/src/web/app/mobile/views/pages/settings.vue
@@ -12,19 +12,20 @@
 		<ul>
 			<li><a @click="signout">%fa:power-off%%i18n:mobile.tags.mk-settings-page.signout%</a></li>
 		</ul>
-		<p><small>ver {{ v }} (葵 aoi)</small></p>
+		<p><small>ver {{ version }} ({{ codename }})</small></p>
 	</div>
 </mk-ui>
 </template>
 
 <script lang="ts">
 import Vue from 'vue';
-import { version } from '../../../config';
+import { version, codename } from '../../../config';
 
 export default Vue.extend({
 	data() {
 		return {
-			v: version
+			version,
+			codename
 		};
 	},
 	mounted() {
diff --git a/swagger.js b/swagger.js
index 0cfd2fff08..f6c2ca7fde 100644
--- a/swagger.js
+++ b/swagger.js
@@ -23,7 +23,7 @@ const defaultSwagger = {
   "swagger": "2.0",
   "info": {
     "title": "Misskey API",
-    "version": "aoi"
+    "version": "nighthike"
   },
   "host": "api.misskey.xyz",
   "schemes": [
@@ -218,8 +218,8 @@ options.apis = files.map(c => {return `${apiRoot}/${c}`;});
 if(fs.existsSync('.config/config.yml')){
   var config = yaml.safeLoad(fs.readFileSync('./.config/config.yml', 'utf8'));
   options.swaggerDefinition.host = `api.${config.url.match(/\:\/\/(.+)$/)[1]}`;
-  options.swaggerDefinition.schemes = config.https.enable ? 
-                                      ['https'] : 
+  options.swaggerDefinition.schemes = config.https.enable ?
+                                      ['https'] :
                                       ['http'];
 }
 
diff --git a/webpack.config.ts b/webpack.config.ts
index 9a952c8ef3..88af49eb53 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -20,6 +20,7 @@ import { licenseHtml } from './src/common/build/license';
 import locales from './locales';
 const meta = require('./package.json');
 const version = meta.version;
+const codename = meta.codename;
 
 //#region Replacer definitions
 global['faReplacement'] = faReplacement;
@@ -76,13 +77,13 @@ module.exports = entries.map(x => {
 		_THEME_COLOR_: constants.themeColor,
 		_COPYRIGHT_: constants.copyright,
 		_VERSION_: version,
+		_CODENAME_: codename,
 		_STATUS_URL_: config.status_url,
 		_STATS_URL_: config.stats_url,
 		_DOCS_URL_: config.docs_url,
 		_API_URL_: config.api_url,
 		_WS_URL_: config.ws_url,
 		_DEV_URL_: config.dev_url,
-		_CH_URL_: config.ch_url,
 		_LANG_: lang,
 		_HOST_: config.host,
 		_HOSTNAME_: config.hostname,

From f839204dd26a6fe59f01acbc43ff26a026277d52 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 09:38:35 +0900
Subject: [PATCH 04/43] Add watch command

---
 package.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/package.json b/package.json
index 3f9e497389..eb65e41db9 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
 		"swagger": "node ./swagger.js",
 		"build": "node --max_old_space_size=16384 ./node_modules/webpack/bin/webpack.js && gulp build",
 		"webpack": "node --max_old_space_size=16384 ./node_modules/webpack/bin/webpack.js",
+		"watch": "node --max_old_space_size=16384 ./node_modules/webpack/bin/webpack.js --watch",
 		"gulp": "gulp build",
 		"rebuild": "gulp rebuild",
 		"clean": "gulp clean",

From 43f882b7783bd495efacee19a148b4c3c2323a96 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 09:59:36 +0900
Subject: [PATCH 05/43] Update README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index c50566cc95..cb8821b1e5 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ Key features
 * Two-Factor Authentication support
 * ServiceWorker support
 * Web API for third-party applications
-* No ads
+* ActivityPub compatible
 
 and more! You can touch with your own eyes at https://misskey.xyz/.
 

From eb443709bfcda81c329b51f95bf02cef85932456 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 13:05:30 +0900
Subject: [PATCH 06/43] #1294

---
 locales/ja.yml                                |  2 +-
 src/api/bot/core.ts                           |  2 +-
 .../app/common/views/components/signin.vue    |  2 +-
 .../app/common/views/components/signup.vue    |  2 +-
 .../common/views/directives/autocomplete.ts   |  2 +-
 src/web/app/dev/views/new-app.vue             |  4 +-
 src/web/app/mobile/views/pages/welcome.vue    |  2 +-
 tools/migration/node.2018-03-28.appname.js    | 40 +++++++++++++++++++
 tools/migration/node.2018-03-28.username.js   | 40 +++++++++++++++++++
 9 files changed, 88 insertions(+), 8 deletions(-)
 create mode 100644 tools/migration/node.2018-03-28.appname.js
 create mode 100644 tools/migration/node.2018-03-28.username.js

diff --git a/locales/ja.yml b/locales/ja.yml
index f826b1b6ca..fd140ecc30 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -147,7 +147,7 @@ common:
       available: "利用できます"
       unavailable: "既に利用されています"
       error: "通信エラー"
-      invalid-format: "a~z、A~Z、0~9、-(ハイフン)が使えます"
+      invalid-format: "a~z、A~Z、0~9、_が使えます"
       too-short: "3文字以上でお願いします!"
       too-long: "20文字以内でお願いします"
       password: "パスワード"
diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts
index 77a68aaee6..d6706e9a1c 100644
--- a/src/api/bot/core.ts
+++ b/src/api/bot/core.ts
@@ -67,7 +67,7 @@ export default class BotCore extends EventEmitter {
 			return await this.context.q(query);
 		}
 
-		if (/^@[a-zA-Z0-9-]+$/.test(query)) {
+		if (/^@[a-zA-Z0-9_]+$/.test(query)) {
 			return await this.showUserCommand(query);
 		}
 
diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue
index 2434684085..273143262b 100644
--- a/src/web/app/common/views/components/signin.vue
+++ b/src/web/app/common/views/components/signin.vue
@@ -1,7 +1,7 @@
 <template>
 <form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit">
 	<label class="user-name">
-		<input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at%
+		<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at%
 	</label>
 	<label class="password">
 		<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock%
diff --git a/src/web/app/common/views/components/signup.vue b/src/web/app/common/views/components/signup.vue
index c2e78aa8a3..e77d849ade 100644
--- a/src/web/app/common/views/components/signup.vue
+++ b/src/web/app/common/views/components/signup.vue
@@ -2,7 +2,7 @@
 <form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off">
 	<label class="username">
 		<p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p>
-		<input v-model="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/>
+		<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/>
 		<p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/@${username}` }}</p>
 		<p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p>
 		<p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p>
diff --git a/src/web/app/common/views/directives/autocomplete.ts b/src/web/app/common/views/directives/autocomplete.ts
index 3440c4212a..94635d301a 100644
--- a/src/web/app/common/views/directives/autocomplete.ts
+++ b/src/web/app/common/views/directives/autocomplete.ts
@@ -77,7 +77,7 @@ class Autocomplete {
 
 		if (mentionIndex != -1 && mentionIndex > emojiIndex) {
 			const username = text.substr(mentionIndex + 1);
-			if (username != '' && username.match(/^[a-zA-Z0-9-]+$/)) {
+			if (username != '' && username.match(/^[a-zA-Z0-9_]+$/)) {
 				this.open('user', username);
 				opened = true;
 			}
diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue
index 344e8468f9..1a796299cb 100644
--- a/src/web/app/dev/views/new-app.vue
+++ b/src/web/app/dev/views/new-app.vue
@@ -6,12 +6,12 @@
 				<b-form-input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/>
 			</b-form-group>
 			<b-form-group label="ID" description="あなたのアプリのID。">
-				<b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9-]{3,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/>
+				<b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9_]{3,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/>
 				<p class="info" v-if="nidState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%確認しています...</p>
 				<p class="info" v-if="nidState == 'ok'" style="color:#3CB7B5">%fa:fw check%利用できます</p>
 				<p class="info" v-if="nidState == 'unavailable'" style="color:#FF1161">%fa:fw exclamation-triangle%既に利用されています</p>
 				<p class="info" v-if="nidState == 'error'" style="color:#FF1161">%fa:fw exclamation-triangle%通信エラー</p>
-				<p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、-(ハイフン)が使えます</p>
+				<p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、_が使えます</p>
 				<p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%3文字以上でお願いします!</p>
 				<p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p>
 			</b-form-group>
diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue
index 3384ee6997..8557448346 100644
--- a/src/web/app/mobile/views/pages/welcome.vue
+++ b/src/web/app/mobile/views/pages/welcome.vue
@@ -6,7 +6,7 @@
 		<p>%fa:lock% ログイン</p>
 		<div>
 			<form @submit.prevent="onSubmit">
-				<input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/>
+				<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/>
 				<input v-model="password" type="password" placeholder="パスワード" required/>
 				<input v-if="user && user.account.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/>
 				<button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button>
diff --git a/tools/migration/node.2018-03-28.appname.js b/tools/migration/node.2018-03-28.appname.js
new file mode 100644
index 0000000000..9f16e47202
--- /dev/null
+++ b/tools/migration/node.2018-03-28.appname.js
@@ -0,0 +1,40 @@
+// for Node.js interpret
+
+const { default: App } = require('../../built/api/models/app');
+const { generate } = require('../../built/crypto_key');
+const { default: zip } = require('@prezzemolo/zip')
+
+const migrate = async (app) => {
+	const result = await User.update(app._id, {
+		$set: {
+			'name_id': app.name_id.replace(/\-/g, '_'),
+			'name_id_lower': app.name_id_lower.replace(/\-/g, '_')
+		}
+	});
+	return result.ok === 1;
+}
+
+async function main() {
+	const count = await App.count({});
+
+	const dop = Number.parseInt(process.argv[2]) || 5
+	const idop = ((count - (count % dop)) / dop) + 1
+
+	return zip(
+		1,
+		async (time) => {
+			console.log(`${time} / ${idop}`)
+			const doc = await App.find({}, {
+				limit: dop, skip: time * dop
+			})
+			return Promise.all(doc.map(migrate))
+		},
+		idop
+	).then(a => {
+		const rv = []
+		a.forEach(e => rv.push(...e))
+		return rv
+	})
+}
+
+main().then(console.dir).catch(console.error)
diff --git a/tools/migration/node.2018-03-28.username.js b/tools/migration/node.2018-03-28.username.js
new file mode 100644
index 0000000000..2222152101
--- /dev/null
+++ b/tools/migration/node.2018-03-28.username.js
@@ -0,0 +1,40 @@
+// for Node.js interpret
+
+const { default: User } = require('../../built/api/models/user');
+const { generate } = require('../../built/crypto_key');
+const { default: zip } = require('@prezzemolo/zip')
+
+const migrate = async (user) => {
+	const result = await User.update(user._id, {
+		$set: {
+			'username': user.username.replace(/\-/g, '_'),
+			'username_lower': user.username_lower.replace(/\-/g, '_')
+		}
+	});
+	return result.ok === 1;
+}
+
+async function main() {
+	const count = await User.count({});
+
+	const dop = Number.parseInt(process.argv[2]) || 5
+	const idop = ((count - (count % dop)) / dop) + 1
+
+	return zip(
+		1,
+		async (time) => {
+			console.log(`${time} / ${idop}`)
+			const doc = await User.find({}, {
+				limit: dop, skip: time * dop
+			})
+			return Promise.all(doc.map(migrate))
+		},
+		idop
+	).then(a => {
+		const rv = []
+		a.forEach(e => rv.push(...e))
+		return rv
+	})
+}
+
+main().then(console.dir).catch(console.error)

From 73bb57480b01ece02bdf43866389bc9ef478f271 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 13:13:10 +0900
Subject: [PATCH 07/43] wip

---
 src/api/models/messaging-history.ts | 12 +++++++++++-
 src/api/models/messaging-message.ts | 11 ++++++-----
 tools/migration/shell.camel-case.js | 22 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/api/models/messaging-history.ts b/src/api/models/messaging-history.ts
index c06987e451..1e79032ed6 100644
--- a/src/api/models/messaging-history.ts
+++ b/src/api/models/messaging-history.ts
@@ -1,3 +1,13 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('messaging_histories') as any; // fuck type definition
+const MessagingHistory = db.get<IMessagingHistory>('messagingHistories');
+export default MessagingHistory;
+
+export type IMessagingHistory = {
+	_id: mongo.ObjectID;
+	updatedAt: Date;
+	userId: mongo.ObjectID;
+	partnerId: mongo.ObjectID;
+	messageId: mongo.ObjectID;
+};
diff --git a/src/api/models/messaging-message.ts b/src/api/models/messaging-message.ts
index fcb356c5ca..026b23cf36 100644
--- a/src/api/models/messaging-message.ts
+++ b/src/api/models/messaging-message.ts
@@ -5,16 +5,17 @@ import { pack as packFile } from './drive-file';
 import db from '../../db/mongodb';
 import parse from '../common/text';
 
-const MessagingMessage = db.get<IMessagingMessage>('messaging_messages');
+const MessagingMessage = db.get<IMessagingMessage>('messagingMessages');
 export default MessagingMessage;
 
 export interface IMessagingMessage {
 	_id: mongo.ObjectID;
-	created_at: Date;
+	createdAt: Date;
 	text: string;
-	user_id: mongo.ObjectID;
-	recipient_id: mongo.ObjectID;
-	is_read: boolean;
+	userId: mongo.ObjectID;
+	recipientId: mongo.ObjectID;
+	isRead: boolean;
+	fileId: mongo.ObjectID;
 }
 
 export function isValidText(text: string): boolean {
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 6d6b01a071..ac0476af0c 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -79,3 +79,25 @@ db.following.update({}, {
 		follower_id: 'followerId',
 	}
 }, false, true);
+
+db.messaging_histories.renameCollection('messagingHistories');
+db.messagingHistories.update({}, {
+	$rename: {
+		updated_at: 'updatedAt',
+		user_id: 'userId',
+		partner: 'partnerId',
+		message: 'messageId',
+	}
+}, false, true);
+
+db.messaging_messages.renameCollection('messagingMessages');
+db.messagingMessages.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		recipient_id: 'recipientId',
+		file_id: 'fileId',
+		is_read: 'isRead'
+	}
+}, false, true);
+

From 7310435584963d782c209163c65048d2cdeb4289 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 13:16:52 +0900
Subject: [PATCH 08/43] wip

---
 src/api/models/meta.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/api/models/meta.ts b/src/api/models/meta.ts
index c7dba8fcba..e885c53733 100644
--- a/src/api/models/meta.ts
+++ b/src/api/models/meta.ts
@@ -1,7 +1,8 @@
 import db from '../../db/mongodb';
 
-export default db.get('meta') as any; // fuck type definition
+const Meta = db.get<IMeta>('meta');
+export default Meta;
 
 export type IMeta = {
-	top_image: string;
+	broadcasts: any[];
 };

From ac12e63a853359b819dfd5df3ef9604a51e27cd4 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 13:20:19 +0900
Subject: [PATCH 09/43] wip

---
 src/api/models/mute.ts              | 12 +++++++++++-
 tools/migration/shell.camel-case.js |  9 +++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/api/models/mute.ts b/src/api/models/mute.ts
index 16018b82f7..fdc8cc714b 100644
--- a/src/api/models/mute.ts
+++ b/src/api/models/mute.ts
@@ -1,3 +1,13 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('mute') as any; // fuck type definition
+const Mute = db.get<IMute>('mute');
+export default Mute;
+
+export interface IMute {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	deletedAt: Date;
+	muterId: mongo.ObjectID;
+	muteeId: mongo.ObjectID;
+}
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index ac0476af0c..9f07bd946d 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -101,3 +101,12 @@ db.messagingMessages.update({}, {
 	}
 }, false, true);
 
+db.mute.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		deleted_at: 'deletedAt',
+		mutee_id: 'muteeId',
+		muter_id: 'muterId',
+	}
+}, false, true);
+

From 69cef75b53671ccd7e0a199d31fa2d6d7c91fe78 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 13:32:05 +0900
Subject: [PATCH 10/43] wip

---
 src/api/endpoints/othello/games.ts      |  4 +--
 src/api/endpoints/othello/games/show.ts |  4 +--
 src/api/endpoints/othello/match.ts      |  4 +--
 src/api/models/othello-game.ts          | 34 ++++++++++++-------------
 src/api/stream/othello-game.ts          | 32 +++++++++++------------
 tools/migration/shell.camel-case.js     | 20 +++++++++++++++
 6 files changed, 59 insertions(+), 39 deletions(-)

diff --git a/src/api/endpoints/othello/games.ts b/src/api/endpoints/othello/games.ts
index 2a6bbb4043..f6e38b8d87 100644
--- a/src/api/endpoints/othello/games.ts
+++ b/src/api/endpoints/othello/games.ts
@@ -1,5 +1,5 @@
 import $ from 'cafy';
-import Game, { pack } from '../../models/othello-game';
+import OthelloGame, { pack } from '../../models/othello-game';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get 'my' parameter
@@ -50,7 +50,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	// Fetch games
-	const games = await Game.find(q, {
+	const games = await OthelloGame.find(q, {
 		sort,
 		limit
 	});
diff --git a/src/api/endpoints/othello/games/show.ts b/src/api/endpoints/othello/games/show.ts
index 2b0db4dd00..c7bd74a39a 100644
--- a/src/api/endpoints/othello/games/show.ts
+++ b/src/api/endpoints/othello/games/show.ts
@@ -1,5 +1,5 @@
 import $ from 'cafy';
-import Game, { pack } from '../../../models/othello-game';
+import OthelloGame, { pack } from '../../../models/othello-game';
 import Othello from '../../../../common/othello/core';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
@@ -7,7 +7,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [gameId, gameIdErr] = $(params.game_id).id().$;
 	if (gameIdErr) return rej('invalid game_id param');
 
-	const game = await Game.findOne({ _id: gameId });
+	const game = await OthelloGame.findOne({ _id: gameId });
 
 	if (game == null) {
 		return rej('game not found');
diff --git a/src/api/endpoints/othello/match.ts b/src/api/endpoints/othello/match.ts
index b73e105ef0..f73386ba7c 100644
--- a/src/api/endpoints/othello/match.ts
+++ b/src/api/endpoints/othello/match.ts
@@ -1,6 +1,6 @@
 import $ from 'cafy';
 import Matching, { pack as packMatching } from '../../models/othello-matching';
-import Game, { pack as packGame } from '../../models/othello-game';
+import OthelloGame, { pack as packGame } from '../../models/othello-game';
 import User from '../../models/user';
 import publishUserStream, { publishOthelloStream } from '../../event';
 import { eighteight } from '../../../common/othello/maps';
@@ -28,7 +28,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		});
 
 		// Create game
-		const game = await Game.insert({
+		const game = await OthelloGame.insert({
 			created_at: new Date(),
 			user1_id: exist.parent_id,
 			user2_id: user._id,
diff --git a/src/api/models/othello-game.ts b/src/api/models/othello-game.ts
index 01c6ca6c00..b9e57632d4 100644
--- a/src/api/models/othello-game.ts
+++ b/src/api/models/othello-game.ts
@@ -3,17 +3,17 @@ import deepcopy = require('deepcopy');
 import db from '../../db/mongodb';
 import { IUser, pack as packUser } from './user';
 
-const Game = db.get<IGame>('othello_games');
-export default Game;
+const OthelloGame = db.get<IOthelloGame>('othelloGames');
+export default OthelloGame;
 
-export interface IGame {
+export interface IOthelloGame {
 	_id: mongo.ObjectID;
-	created_at: Date;
-	started_at: Date;
-	user1_id: mongo.ObjectID;
-	user2_id: mongo.ObjectID;
-	user1_accepted: boolean;
-	user2_accepted: boolean;
+	createdAt: Date;
+	startedAt: Date;
+	user1Id: mongo.ObjectID;
+	user2Id: mongo.ObjectID;
+	user1Accepted: boolean;
+	user2Accepted: boolean;
 
 	/**
 	 * どちらのプレイヤーが先行(黒)か
@@ -22,9 +22,9 @@ export interface IGame {
 	 */
 	black: number;
 
-	is_started: boolean;
-	is_ended: boolean;
-	winner_id: mongo.ObjectID;
+	isStarted: boolean;
+	isEnded: boolean;
+	winnerId: mongo.ObjectID;
 	logs: Array<{
 		at: Date;
 		color: boolean;
@@ -33,9 +33,9 @@ export interface IGame {
 	settings: {
 		map: string[];
 		bw: string | number;
-		is_llotheo: boolean;
-		can_put_everywhere: boolean;
-		looped_board: boolean;
+		isLlotheo: boolean;
+		canPutEverywhere: boolean;
+		loopedBoard: boolean;
 	};
 	form1: any;
 	form2: any;
@@ -62,11 +62,11 @@ export const pack = (
 
 	// Populate the game if 'game' is ID
 	if (mongo.ObjectID.prototype.isPrototypeOf(game)) {
-		_game = await Game.findOne({
+		_game = await OthelloGame.findOne({
 			_id: game
 		});
 	} else if (typeof game === 'string') {
-		_game = await Game.findOne({
+		_game = await OthelloGame.findOne({
 			_id: new mongo.ObjectID(game)
 		});
 	} else {
diff --git a/src/api/stream/othello-game.ts b/src/api/stream/othello-game.ts
index 1c846f27ae..45a931c7e7 100644
--- a/src/api/stream/othello-game.ts
+++ b/src/api/stream/othello-game.ts
@@ -1,7 +1,7 @@
 import * as websocket from 'websocket';
 import * as redis from 'redis';
 import * as CRC32 from 'crc-32';
-import Game, { pack } from '../models/othello-game';
+import OthelloGame, { pack } from '../models/othello-game';
 import { publishOthelloGameStream } from '../event';
 import Othello from '../../common/othello/core';
 import * as maps from '../../common/othello/maps';
@@ -60,14 +60,14 @@ export default function(request: websocket.request, connection: websocket.connec
 	});
 
 	async function updateSettings(settings) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (game.is_started) return;
 		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
 		if (game.user1_id.equals(user._id) && game.user1_accepted) return;
 		if (game.user2_id.equals(user._id) && game.user2_accepted) return;
 
-		await Game.update({ _id: gameId }, {
+		await OthelloGame.update({ _id: gameId }, {
 			$set: {
 				settings
 			}
@@ -77,7 +77,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	}
 
 	async function initForm(form) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (game.is_started) return;
 		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
@@ -88,7 +88,7 @@ export default function(request: websocket.request, connection: websocket.connec
 			form2: form
 		};
 
-		await Game.update({ _id: gameId }, {
+		await OthelloGame.update({ _id: gameId }, {
 			$set: set
 		});
 
@@ -99,7 +99,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	}
 
 	async function updateForm(id, value) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (game.is_started) return;
 		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
@@ -118,7 +118,7 @@ export default function(request: websocket.request, connection: websocket.connec
 			form1: form
 		};
 
-		await Game.update({ _id: gameId }, {
+		await OthelloGame.update({ _id: gameId }, {
 			$set: set
 		});
 
@@ -138,14 +138,14 @@ export default function(request: websocket.request, connection: websocket.connec
 	}
 
 	async function accept(accept: boolean) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (game.is_started) return;
 
 		let bothAccepted = false;
 
 		if (game.user1_id.equals(user._id)) {
-			await Game.update({ _id: gameId }, {
+			await OthelloGame.update({ _id: gameId }, {
 				$set: {
 					user1_accepted: accept
 				}
@@ -158,7 +158,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 			if (accept && game.user2_accepted) bothAccepted = true;
 		} else if (game.user2_id.equals(user._id)) {
-			await Game.update({ _id: gameId }, {
+			await OthelloGame.update({ _id: gameId }, {
 				$set: {
 					user2_accepted: accept
 				}
@@ -177,7 +177,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		if (bothAccepted) {
 			// 3秒後、まだacceptされていたらゲーム開始
 			setTimeout(async () => {
-				const freshGame = await Game.findOne({ _id: gameId });
+				const freshGame = await OthelloGame.findOne({ _id: gameId });
 				if (freshGame == null || freshGame.is_started || freshGame.is_ended) return;
 				if (!freshGame.user1_accepted || !freshGame.user2_accepted) return;
 
@@ -196,7 +196,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 				const map = freshGame.settings.map != null ? freshGame.settings.map : getRandomMap();
 
-				await Game.update({ _id: gameId }, {
+				await OthelloGame.update({ _id: gameId }, {
 					$set: {
 						started_at: new Date(),
 						is_started: true,
@@ -222,7 +222,7 @@ export default function(request: websocket.request, connection: websocket.connec
 						winner = null;
 					}
 
-					await Game.update({
+					await OthelloGame.update({
 						_id: gameId
 					}, {
 						$set: {
@@ -245,7 +245,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 	// 石を打つ
 	async function set(pos) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (!game.is_started) return;
 		if (game.is_ended) return;
@@ -288,7 +288,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 		const crc32 = CRC32.str(game.logs.map(x => x.pos.toString()).join('') + pos.toString());
 
-		await Game.update({
+		await OthelloGame.update({
 			_id: gameId
 		}, {
 			$set: {
@@ -314,7 +314,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	}
 
 	async function check(crc32) {
-		const game = await Game.findOne({ _id: gameId });
+		const game = await OthelloGame.findOne({ _id: gameId });
 
 		if (!game.is_started) return;
 
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 9f07bd946d..11c6fe401d 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -1,3 +1,5 @@
+// このスクリプトを走らせる前か後に notifications コレクションはdropしてください
+
 db.access_tokens.renameCollection('accessTokens');
 db.accessTokens.update({}, {
 	$rename: {
@@ -110,3 +112,21 @@ db.mute.update({}, {
 	}
 }, false, true);
 
+db.othello_games.renameCollection('othelloGames');
+db.othelloGames.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		started_at: 'startedAt',
+		is_started: 'isStarted',
+		is_ended: 'isEnded',
+		user1_id: 'user1Id',
+		user2_id: 'user2Id',
+		user1_accepted: 'user1Accepted',
+		user2_accepted: 'user2Accepted',
+		winner_id: 'winnerId',
+		'settings.is_llotheo': 'settings.isLlotheo',
+		'settings.can_put_everywhere': 'settings.canPutEverywhere',
+		'settings.looped_board': 'settings.loopedBoard',
+	}
+}, false, true);
+

From 46f70dbbfb07ef5b9e8efd184aea730d29378cfb Mon Sep 17 00:00:00 2001
From: "greenkeeper[bot]" <greenkeeper[bot]@users.noreply.github.com>
Date: Wed, 28 Mar 2018 06:47:01 +0000
Subject: [PATCH 11/43] fix(package): update gulp-typescript to version 4.0.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index eb65e41db9..75eaa57419 100644
--- a/package.json
+++ b/package.json
@@ -126,7 +126,7 @@
 		"gulp-sourcemaps": "2.6.4",
 		"gulp-stylus": "2.7.0",
 		"gulp-tslint": "8.1.3",
-		"gulp-typescript": "4.0.1",
+		"gulp-typescript": "4.0.2",
 		"gulp-uglify": "3.0.0",
 		"gulp-util": "3.0.8",
 		"hard-source-webpack-plugin": "0.6.4",

From 70e151805a97c9f08abd91e3170806f2bc400112 Mon Sep 17 00:00:00 2001
From: "greenkeeper[bot]" <greenkeeper[bot]@users.noreply.github.com>
Date: Wed, 28 Mar 2018 06:50:48 +0000
Subject: [PATCH 12/43] fix(package): update element-ui to version 2.3.0

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index eb65e41db9..efede0bac1 100644
--- a/package.json
+++ b/package.json
@@ -103,7 +103,7 @@
 		"deepcopy": "0.6.3",
 		"diskusage": "0.2.4",
 		"elasticsearch": "14.2.1",
-		"element-ui": "2.2.2",
+		"element-ui": "2.3.0",
 		"emojilib": "2.2.12",
 		"escape-regexp": "0.0.1",
 		"eslint": "4.19.1",

From 02be56cfc0feaa6dad6a63759eeae0ec7dfbfff4 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 15:54:47 +0900
Subject: [PATCH 13/43] wip

---
 src/api/models/othello-matching.ts  |  8 ++++----
 src/api/models/poll-vote.ts         | 12 +++++++++++-
 tools/migration/shell.camel-case.js | 17 +++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/api/models/othello-matching.ts b/src/api/models/othello-matching.ts
index 5cc39cae13..9c84d7fb9f 100644
--- a/src/api/models/othello-matching.ts
+++ b/src/api/models/othello-matching.ts
@@ -3,14 +3,14 @@ import deepcopy = require('deepcopy');
 import db from '../../db/mongodb';
 import { IUser, pack as packUser } from './user';
 
-const Matching = db.get<IMatching>('othello_matchings');
+const Matching = db.get<IMatching>('othelloMatchings');
 export default Matching;
 
 export interface IMatching {
 	_id: mongo.ObjectID;
-	created_at: Date;
-	parent_id: mongo.ObjectID;
-	child_id: mongo.ObjectID;
+	createdAt: Date;
+	parentId: mongo.ObjectID;
+	childId: mongo.ObjectID;
 }
 
 /**
diff --git a/src/api/models/poll-vote.ts b/src/api/models/poll-vote.ts
index af77a2643e..3e883f2137 100644
--- a/src/api/models/poll-vote.ts
+++ b/src/api/models/poll-vote.ts
@@ -1,3 +1,13 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('poll_votes') as any; // fuck type definition
+const PollVote = db.get<IPollVote>('pollVotes');
+export default PollVote;
+
+export interface IPollVote {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	userId: mongo.ObjectID;
+	postId: mongo.ObjectID;
+	choice: number;
+}
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 11c6fe401d..6045dfa00c 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -130,3 +130,20 @@ db.othelloGames.update({}, {
 	}
 }, false, true);
 
+db.othello_matchings.renameCollection('othelloMatchings');
+db.othelloMatchings.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		parent_id: 'parentId',
+		child_id: 'childId'
+	}
+}, false, true);
+
+db.poll_votes.renameCollection('pollVotes');
+db.pollVotes.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		post_id: 'postId'
+	}
+}, false, true);

From 65069d5fdb9af3214d62fcd48f140c9e735fa892 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 15:59:34 +0900
Subject: [PATCH 14/43] wip

---
 src/api/models/post-reaction.ts     |  8 +++++---
 src/api/models/post-watching.ts     | 11 ++++++++++-
 tools/migration/shell.camel-case.js |  9 +++++++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/api/models/post-reaction.ts b/src/api/models/post-reaction.ts
index 639a70e006..f581f01535 100644
--- a/src/api/models/post-reaction.ts
+++ b/src/api/models/post-reaction.ts
@@ -4,13 +4,15 @@ import db from '../../db/mongodb';
 import Reaction from './post-reaction';
 import { pack as packUser } from './user';
 
-const PostReaction = db.get<IPostReaction>('post_reactions');
+const PostReaction = db.get<IPostReaction>('postReactions');
 export default PostReaction;
 
 export interface IPostReaction {
 	_id: mongo.ObjectID;
-	created_at: Date;
-	deleted_at: Date;
+	createdAt: Date;
+	deletedAt: Date;
+	postId: mongo.ObjectID;
+	userId: mongo.ObjectID;
 	reaction: string;
 }
 
diff --git a/src/api/models/post-watching.ts b/src/api/models/post-watching.ts
index 41d37e2703..907909a50f 100644
--- a/src/api/models/post-watching.ts
+++ b/src/api/models/post-watching.ts
@@ -1,3 +1,12 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('post_watching') as any; // fuck type definition
+const PostWatching = db.get<IPostWatching>('postWatching');
+export default PostWatching;
+
+export interface IPostWatching {
+	_id: mongo.ObjectID;
+	createdAt: Date;
+	userId: mongo.ObjectID;
+	postId: mongo.ObjectID;
+}
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 6045dfa00c..2a5456b4d0 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -147,3 +147,12 @@ db.pollVotes.update({}, {
 		post_id: 'postId'
 	}
 }, false, true);
+
+db.post_reactions.renameCollection('postReactions');
+db.postReactions.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		post_id: 'postId'
+	}
+}, false, true);

From bed17efd1b40e05e49b4de50c118f2acf804b95e Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:04:44 +0900
Subject: [PATCH 15/43] wip

---
 src/api/models/post.ts              | 18 ++++++++----------
 tools/migration/shell.camel-case.js | 22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/api/models/post.ts b/src/api/models/post.ts
index c37c8371c0..fc44256516 100644
--- a/src/api/models/post.ts
+++ b/src/api/models/post.ts
@@ -20,18 +20,16 @@ export function isValidText(text: string): boolean {
 
 export type IPost = {
 	_id: mongo.ObjectID;
-	channel_id: mongo.ObjectID;
-	created_at: Date;
-	media_ids: mongo.ObjectID[];
-	reply_id: mongo.ObjectID;
-	repost_id: mongo.ObjectID;
+	channelId: mongo.ObjectID;
+	createdAt: Date;
+	mediaIds: mongo.ObjectID[];
+	replyId: mongo.ObjectID;
+	repostId: mongo.ObjectID;
 	poll: any; // todo
 	text: string;
-	user_id: mongo.ObjectID;
-	app_id: mongo.ObjectID;
-	category: string;
-	is_category_verified: boolean;
-	via_mobile: boolean;
+	userId: mongo.ObjectID;
+	appId: mongo.ObjectID;
+	viaMobile: boolean;
 	geo: {
 		latitude: number;
 		longitude: number;
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 2a5456b4d0..326d0a1b0f 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -156,3 +156,25 @@ db.postReactions.update({}, {
 		post_id: 'postId'
 	}
 }, false, true);
+
+db.post_watching.renameCollection('postWatching');
+db.postWatching.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+		post_id: 'postId'
+	}
+}, false, true);
+
+db.posts.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		channel_id: 'channelId',
+		user_id: 'userId',
+		app_id: 'appId',
+		media_ids: 'mediaIds',
+		reply_id: 'replyId',
+		repost_id: 'repostId',
+		via_mobile: 'viaMobile'
+	}
+}, false, true);

From b6c190e1fd915178100357009707aaa39a7bc687 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:07:48 +0900
Subject: [PATCH 16/43] wip

---
 tools/migration/shell.camel-case.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 326d0a1b0f..a7e8afcdce 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -175,6 +175,8 @@ db.posts.update({}, {
 		media_ids: 'mediaIds',
 		reply_id: 'replyId',
 		repost_id: 'repostId',
-		via_mobile: 'viaMobile'
+		via_mobile: 'viaMobile',
+		'_reply.user_id': '_reply.userId',
+		'_repost.user_id': '_repost.userId',
 	}
 }, false, true);

From 9bcd3cde46c457f0f59dbf8694652615ba9b272f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:09:49 +0900
Subject: [PATCH 17/43] wip

---
 src/api/models/signin.ts            | 5 +++++
 tools/migration/shell.camel-case.js | 7 +++++++
 2 files changed, 12 insertions(+)

diff --git a/src/api/models/signin.ts b/src/api/models/signin.ts
index 262c8707ed..62ee796d85 100644
--- a/src/api/models/signin.ts
+++ b/src/api/models/signin.ts
@@ -7,6 +7,11 @@ export default Signin;
 
 export interface ISignin {
 	_id: mongo.ObjectID;
+	createdAt: Date;
+	userId: mongo.ObjectID;
+	ip: string;
+	headers: any;
+	success: boolean;
 }
 
 /**
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index a7e8afcdce..533868cdc4 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -180,3 +180,10 @@ db.posts.update({}, {
 		'_repost.user_id': '_repost.userId',
 	}
 }, false, true);
+
+db.signin.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		user_id: 'userId',
+	}
+}, false, true);

From efb7c71d88f177cb245873f3c705c82c4647b1ed Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:11:50 +0900
Subject: [PATCH 18/43] wip

---
 src/api/models/sw-subscription.ts   | 12 +++++++++++-
 tools/migration/shell.camel-case.js |  7 +++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/api/models/sw-subscription.ts b/src/api/models/sw-subscription.ts
index ecca04cb91..235c801c7d 100644
--- a/src/api/models/sw-subscription.ts
+++ b/src/api/models/sw-subscription.ts
@@ -1,3 +1,13 @@
+import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-export default db.get('sw_subscriptions') as any; // fuck type definition
+const SwSubscription = db.get<ISwSubscription>('swSubscriptions');
+export default SwSubscription;
+
+export interface ISwSubscription {
+	_id: mongo.ObjectID;
+	userId: mongo.ObjectID;
+	endpoint: string;
+	auth: string;
+	publickey: string;
+}
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 533868cdc4..9cb0baaaf5 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -187,3 +187,10 @@ db.signin.update({}, {
 		user_id: 'userId',
 	}
 }, false, true);
+
+db.sw_subscriptions.renameCollection('swSubscriptions');
+db.swSubscriptions.update({}, {
+	$rename: {
+		user_id: 'userId',
+	}
+}, false, true);

From 7d4d9dbaa61f2eaaa66eac2d9ac282c41044e2c7 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:20:46 +0900
Subject: [PATCH 19/43] wip

---
 src/api/models/user.ts              |  2 +-
 src/api/private/signup.ts           |  2 --
 tools/migration/shell.camel-case.js | 33 +++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/api/models/user.ts b/src/api/models/user.ts
index e73c95faf2..9aa7c4efae 100644
--- a/src/api/models/user.ts
+++ b/src/api/models/user.ts
@@ -46,7 +46,7 @@ export type ILocalAccount = {
 	password: string;
 	token: string;
 	twitter: {
-		access_token: string;
+		accessToken: string;
 		access_token_secret: string;
 		user_id: string;
 		screen_name: string;
diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts
index 96e0495709..29d75b62f9 100644
--- a/src/api/private/signup.ts
+++ b/src/api/private/signup.ts
@@ -115,8 +115,6 @@ export default async (req: express.Request, res: express.Response) => {
 		following_count: 0,
 		name: name,
 		posts_count: 0,
-		likes_count: 0,
-		liked_count: 0,
 		drive_capacity: 1073741824, // 1GB
 		username: username,
 		username_lower: username.toLowerCase(),
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index 9cb0baaaf5..afe831e5b7 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -194,3 +194,36 @@ db.swSubscriptions.update({}, {
 		user_id: 'userId',
 	}
 }, false, true);
+
+db.users.update({}, {
+	$rename: {
+		created_at: 'createdAt',
+		deleted_at: 'deletedAt',
+		followers_count: 'followersCount',
+		following_count: 'followingCount',
+		posts_count: 'postsCount',
+		drive_capacity: 'driveCapacity',
+		username_lower: 'usernameLower',
+		avatar_id: 'avatarId',
+		banner_id: 'bannerId',
+		pinned_post_id: 'pinnedPostId',
+		is_suspended: 'isSuspended',
+		host_lower: 'hostLower',
+		'twitter.access_token': 'twitter.accessToken',
+		'twitter.access_token_secret': 'twitter.accessTokenSecret',
+		'twitter.user_id': 'twitter.userId',
+		'twitter.screen_name': 'twitter.screenName',
+		'line.user_id': 'line.userId',
+		last_used_at: 'lastUsedAt',
+		is_bot: 'isBot',
+		is_pro: 'isPro',
+		two_factor_secret: 'twoFactorSecret',
+		two_factor_enabled: 'twoFactorEnabled',
+		client_settings: 'clientSettings'
+	},
+	$unset: {
+		likes_count: '',
+		liked_count: '',
+		latest_post: ''
+	}
+}, false, true);

From 3d5cdb8d2d60932caf1d29b0581c7d6243e06e37 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:39:14 +0900
Subject: [PATCH 20/43] wip

---
 src/api/authenticate.ts                       |   4 +-
 src/api/bot/core.ts                           |   2 +-
 src/api/bot/interfaces/line.ts                |  10 +-
 src/api/common/add-file-to-drive.ts           | 306 ++++++++++++++++++
 src/api/common/drive/add-file.ts              |  16 +-
 src/api/common/get-friends.ts                 |   8 +-
 src/api/common/notify.ts                      |  18 +-
 src/api/common/push-sw.ts                     |   4 +-
 src/api/common/read-messaging-message.ts      |  12 +-
 src/api/common/read-notification.ts           |   8 +-
 src/api/common/watch-post.ts                  |  14 +-
 src/api/endpoints/aggregation/posts.ts        |  16 +-
 .../endpoints/aggregation/posts/reaction.ts   |  16 +-
 .../endpoints/aggregation/posts/reactions.ts  |  16 +-
 src/api/endpoints/aggregation/posts/reply.ts  |  14 +-
 src/api/endpoints/aggregation/posts/repost.ts |  16 +-
 src/api/endpoints/aggregation/users.ts        |   8 +-
 .../endpoints/aggregation/users/activity.ts   |  24 +-
 .../endpoints/aggregation/users/followers.ts  |  20 +-
 .../endpoints/aggregation/users/following.ts  |  20 +-
 src/api/endpoints/aggregation/users/post.ts   |  24 +-
 .../endpoints/aggregation/users/reaction.ts   |  16 +-
 src/api/endpoints/app/create.ts               |  16 +-
 src/api/endpoints/app/name_id/available.ts    |  18 +-
 src/api/endpoints/app/show.ts                 |  24 +-
 src/api/endpoints/auth/accept.ts              |  14 +-
 src/api/endpoints/auth/session/generate.ts    |   4 +-
 src/api/endpoints/auth/session/show.ts        |   6 +-
 src/api/endpoints/auth/session/userkey.ts     |  12 +-
 src/api/endpoints/channels/create.ts          |  12 +-
 src/api/endpoints/channels/posts.ts           |   8 +-
 src/api/endpoints/channels/show.ts            |   6 +-
 src/api/endpoints/channels/unwatch.ts         |  16 +-
 src/api/endpoints/channels/watch.ts           |  20 +-
 src/api/endpoints/drive.ts                    |   4 +-
 src/api/endpoints/drive/files.ts              |  10 +-
 src/api/endpoints/drive/files/create.ts       |   6 +-
 src/api/endpoints/drive/files/find.ts         |  10 +-
 src/api/endpoints/drive/files/show.ts         |   8 +-
 src/api/endpoints/drive/files/update.ts       |  22 +-
 .../endpoints/drive/files/upload_from_url.ts  |   6 +-
 src/api/endpoints/drive/folders.ts            |  10 +-
 src/api/endpoints/drive/folders/create.ts     |  14 +-
 src/api/endpoints/drive/folders/find.ts       |  10 +-
 src/api/endpoints/drive/folders/show.ts       |   8 +-
 src/api/endpoints/drive/folders/update.ts     |  32 +-
 src/api/endpoints/drive/stream.ts             |   2 +-
 src/api/endpoints/following/create.ts         |  22 +-
 src/api/endpoints/following/delete.ts         |  18 +-
 src/api/endpoints/i.ts                        |   2 +-
 src/api/endpoints/i/2fa/done.ts               |   8 +-
 src/api/endpoints/i/2fa/register.ts           |   2 +-
 src/api/endpoints/i/2fa/unregister.ts         |   4 +-
 src/api/endpoints/i/appdata/get.ts            |   4 +-
 src/api/endpoints/i/appdata/set.ts            |   8 +-
 src/api/endpoints/i/authorized_apps.ts        |   4 +-
 src/api/endpoints/i/favorites.ts              |   2 +-
 src/api/endpoints/i/notifications.ts          |  12 +-
 src/api/endpoints/i/pin.ts                    |  10 +-
 src/api/endpoints/i/signin_history.ts         |   2 +-
 src/api/endpoints/i/update.ts                 |  30 +-
 src/api/endpoints/i/update_client_setting.ts  |   4 +-
 src/api/endpoints/i/update_home.ts            |   6 +-
 src/api/endpoints/i/update_mobile_home.ts     |   6 +-
 src/api/endpoints/messaging/history.ts        |  14 +-
 src/api/endpoints/messaging/messages.ts       |  14 +-
 .../endpoints/messaging/messages/create.ts    |  74 ++---
 src/api/endpoints/messaging/unread.ts         |  12 +-
 src/api/endpoints/mute/create.ts              |  18 +-
 src/api/endpoints/mute/delete.ts              |  14 +-
 src/api/endpoints/mute/list.ts                |   8 +-
 src/api/endpoints/my/apps.ts                  |   2 +-
 .../notifications/get_unread_count.ts         |  12 +-
 .../notifications/mark_as_read_all.ts         |   6 +-
 src/api/endpoints/othello/games.ts            |   8 +-
 src/api/endpoints/othello/games/show.ts       |   6 +-
 src/api/endpoints/othello/invitations.ts      |   2 +-
 src/api/endpoints/othello/match.ts            |  40 +--
 src/api/endpoints/othello/match/cancel.ts     |   2 +-
 src/api/endpoints/posts.ts                    |   8 +-
 src/api/endpoints/posts/categorize.ts         |   8 +-
 src/api/endpoints/posts/context.ts            |  14 +-
 src/api/endpoints/posts/create.ts             | 152 ++++-----
 src/api/endpoints/posts/favorites/create.ts   |  16 +-
 src/api/endpoints/posts/favorites/delete.ts   |  10 +-
 src/api/endpoints/posts/mentions.ts           |   2 +-
 .../endpoints/posts/polls/recommendation.ts   |   8 +-
 src/api/endpoints/posts/polls/vote.ts         |  32 +-
 src/api/endpoints/posts/reactions.ts          |  10 +-
 src/api/endpoints/posts/reactions/create.ts   |  42 +--
 src/api/endpoints/posts/reactions/delete.ts   |  14 +-
 src/api/endpoints/posts/replies.ts            |   8 +-
 src/api/endpoints/posts/reposts.ts            |   8 +-
 src/api/endpoints/posts/search.ts             |  74 ++---
 src/api/endpoints/posts/show.ts               |   6 +-
 src/api/endpoints/posts/timeline.ts           |  30 +-
 src/api/endpoints/posts/trend.ts              |   8 +-
 src/api/endpoints/stats.ts                    |   4 +-
 src/api/endpoints/sw/register.ts              |   6 +-
 src/api/endpoints/username/available.ts       |   2 +-
 src/api/endpoints/users.ts                    |   4 +-
 src/api/endpoints/users/followers.ts          |  14 +-
 src/api/endpoints/users/following.ts          |  14 +-
 .../users/get_frequently_replied_users.ts     |  20 +-
 src/api/endpoints/users/posts.ts              |  22 +-
 src/api/endpoints/users/recommendation.ts     |   4 +-
 src/api/endpoints/users/search.ts             |   2 +-
 src/api/endpoints/users/search_by_username.ts |   2 +-
 src/api/endpoints/users/show.ts               |  56 ++--
 src/api/models/channel-watching.ts            |   2 +-
 src/api/models/channel.ts                     |   2 +-
 src/api/models/messaging-message.ts           |   8 +-
 src/api/models/notification.ts                |  22 +-
 src/api/models/othello-game.ts                |   8 +-
 src/api/models/othello-matching.ts            |   4 +-
 src/api/models/post-reaction.ts               |   2 +-
 src/api/models/post.ts                        |  36 +--
 src/api/models/user.ts                        | 117 +++----
 src/api/private/signin.ts                     |  10 +-
 src/api/private/signup.ts                     |  22 +-
 src/api/service/github.ts                     |   2 +-
 src/api/service/twitter.ts                    |  10 +-
 src/api/stream/home.ts                        |  16 +-
 src/api/stream/othello-game.ts                |  96 +++---
 src/api/stream/othello.ts                     |   6 +-
 src/api/streaming.ts                          |   2 +-
 src/common/get-post-summary.ts                |   4 +-
 src/common/othello/ai/back.ts                 |  28 +-
 src/common/othello/ai/front.ts                |  16 +-
 src/common/user/get-summary.ts                |   2 +-
 src/config.ts                                 |   2 +-
 src/tools/analysis/extract-user-domains.ts    |   2 +-
 src/tools/analysis/extract-user-keywords.ts   |   2 +-
 src/tools/analysis/predict-user-interst.ts    |   2 +-
 src/web/app/auth/views/form.vue               |   2 +-
 src/web/app/ch/tags/channel.tag               |  20 +-
 src/web/app/common/define-widget.ts           |   4 +-
 src/web/app/common/mios.ts                    |   4 +-
 src/web/app/common/scripts/streaming/home.ts  |   2 +-
 .../views/components/messaging-room.form.vue  |   6 +-
 .../components/messaging-room.message.vue     |   6 +-
 .../views/components/messaging-room.vue       |  14 +-
 .../app/common/views/components/messaging.vue |  12 +-
 .../common/views/components/othello.game.vue  |  54 ++--
 .../views/components/othello.gameroom.vue     |   2 +-
 .../common/views/components/othello.room.vue  |  26 +-
 .../app/common/views/components/othello.vue   |  10 +-
 src/web/app/common/views/components/poll.vue  |   2 +-
 .../app/common/views/components/post-menu.vue |   4 +-
 .../views/components/reaction-picker.vue      |   2 +-
 .../app/common/views/components/signin.vue    |   4 +-
 .../views/components/twitter-setting.vue      |   4 +-
 .../app/common/views/components/uploader.vue  |   2 +-
 .../views/components/welcome-timeline.vue     |   2 +-
 .../app/common/views/widgets/slideshow.vue    |   2 +-
 src/web/app/desktop/api/update-avatar.ts      |   6 +-
 src/web/app/desktop/api/update-banner.ts      |   6 +-
 .../app/desktop/views/components/activity.vue |   2 +-
 .../desktop/views/components/drive.file.vue   |  14 +-
 .../desktop/views/components/drive.folder.vue |  10 +-
 .../views/components/drive.nav-folder.vue     |   8 +-
 .../app/desktop/views/components/drive.vue    |  28 +-
 .../views/components/follow-button.vue        |   4 +-
 .../desktop/views/components/followers.vue    |   4 +-
 .../desktop/views/components/following.vue    |   4 +-
 src/web/app/desktop/views/components/home.vue |  20 +-
 .../desktop/views/components/media-image.vue  |   2 +-
 .../views/components/notifications.vue        |  22 +-
 .../views/components/post-detail.sub.vue      |   8 +-
 .../desktop/views/components/post-detail.vue  |  16 +-
 .../desktop/views/components/post-form.vue    |   8 +-
 .../desktop/views/components/post-preview.vue |   8 +-
 .../views/components/posts.post.sub.vue       |   8 +-
 .../desktop/views/components/posts.post.vue   |  20 +-
 .../app/desktop/views/components/posts.vue    |   4 +-
 .../desktop/views/components/repost-form.vue  |   2 +-
 .../desktop/views/components/settings.2fa.vue |   8 +-
 .../views/components/settings.profile.vue     |   4 +-
 .../views/components/settings.signins.vue     |   2 +-
 .../app/desktop/views/components/settings.vue |  10 +-
 .../views/components/sub-post-content.vue     |   4 +-
 .../app/desktop/views/components/timeline.vue |   4 +-
 .../desktop/views/components/ui.header.vue    |   4 +-
 .../desktop/views/components/user-preview.vue |   8 +-
 .../views/components/widget-container.vue     |   4 +-
 .../app/desktop/views/components/window.vue   |   4 +-
 src/web/app/desktop/views/pages/home.vue      |   2 +-
 src/web/app/desktop/views/pages/post.vue      |   2 +-
 .../pages/user/user.followers-you-know.vue    |   2 +-
 .../desktop/views/pages/user/user.friends.vue |   2 +-
 .../desktop/views/pages/user/user.home.vue    |   6 +-
 .../desktop/views/pages/user/user.photos.vue  |   2 +-
 .../desktop/views/pages/user/user.profile.vue |  12 +-
 .../views/pages/user/user.timeline.vue        |   4 +-
 .../views/widgets/channel.channel.form.vue    |   4 +-
 .../desktop/views/widgets/channel.channel.vue |   2 +-
 src/web/app/desktop/views/widgets/channel.vue |   2 +-
 src/web/app/dev/views/app.vue                 |   2 +-
 src/web/app/dev/views/new-app.vue             |   6 +-
 src/web/app/mobile/api/post.ts                |   2 +-
 .../app/mobile/views/components/activity.vue  |   2 +-
 .../views/components/drive.file-detail.vue    |  14 +-
 .../mobile/views/components/drive.file.vue    |   4 +-
 src/web/app/mobile/views/components/drive.vue |  28 +-
 .../mobile/views/components/follow-button.vue |   4 +-
 .../mobile/views/components/media-image.vue   |   2 +-
 .../mobile/views/components/notification.vue  |   8 +-
 .../mobile/views/components/notifications.vue |   4 +-
 .../app/mobile/views/components/post-card.vue |   2 +-
 .../views/components/post-detail.sub.vue      |   2 +-
 .../mobile/views/components/post-detail.vue   |  12 +-
 .../app/mobile/views/components/post-form.vue |   8 +-
 .../mobile/views/components/post-preview.vue  |   2 +-
 .../app/mobile/views/components/post.sub.vue  |   2 +-
 src/web/app/mobile/views/components/post.vue  |  14 +-
 src/web/app/mobile/views/components/posts.vue |   4 +-
 .../views/components/sub-post-content.vue     |   4 +-
 .../app/mobile/views/components/timeline.vue  |   2 +-
 .../app/mobile/views/components/ui.header.vue |   4 +-
 .../mobile/views/components/user-timeline.vue |   4 +-
 src/web/app/mobile/views/pages/followers.vue  |   4 +-
 src/web/app/mobile/views/pages/following.vue  |   4 +-
 src/web/app/mobile/views/pages/home.vue       |  22 +-
 src/web/app/mobile/views/pages/post.vue       |   2 +-
 .../mobile/views/pages/profile-setting.vue    |   4 +-
 src/web/app/mobile/views/pages/user.vue       |   6 +-
 .../pages/user/home.followers-you-know.vue    |   2 +-
 .../mobile/views/pages/user/home.friends.vue  |   2 +-
 .../mobile/views/pages/user/home.photos.vue   |   2 +-
 .../mobile/views/pages/user/home.posts.vue    |   2 +-
 src/web/app/mobile/views/pages/user/home.vue  |   4 +-
 src/web/app/mobile/views/pages/welcome.vue    |   4 +-
 src/web/app/stats/tags/index.tag              |   2 +-
 src/web/docs/api/endpoints/posts/create.yaml  |   6 +-
 src/web/docs/api/entities/drive-file.yaml     |   6 +-
 src/web/docs/api/entities/post.yaml           |  12 +-
 src/web/docs/api/entities/user.yaml           |  26 +-
 237 files changed, 1661 insertions(+), 1354 deletions(-)
 create mode 100644 src/api/common/add-file-to-drive.ts

diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts
index 537c3d1e1f..7b3983a838 100644
--- a/src/api/authenticate.ts
+++ b/src/api/authenticate.ts
@@ -55,10 +55,10 @@ export default (req: express.Request) => new Promise<IAuthContext>(async (resolv
 		}
 
 		const app = await App
-			.findOne({ _id: accessToken.app_id });
+			.findOne({ _id: accessToken.appId });
 
 		const user = await User
-			.findOne({ _id: accessToken.user_id });
+			.findOne({ _id: accessToken.userId });
 
 		return resolve({
 			app: app,
diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts
index d6706e9a1c..9e699572de 100644
--- a/src/api/bot/core.ts
+++ b/src/api/bot/core.ts
@@ -208,7 +208,7 @@ class SigninContext extends Context {
 		if (this.temporaryUser == null) {
 			// Fetch user
 			const user: IUser = await User.findOne({
-				username_lower: query.toLowerCase(),
+				usernameLower: query.toLowerCase(),
 				host: null
 			}, {
 				fields: {
diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts
index 8036b2fde4..dc600125c5 100644
--- a/src/api/bot/interfaces/line.ts
+++ b/src/api/bot/interfaces/line.ts
@@ -115,7 +115,7 @@ class LineBot extends BotCore {
 			actions.push({
 				type: 'uri',
 				label: 'Twitterアカウントを見る',
-				uri: `https://twitter.com/${user.account.twitter.screen_name}`
+				uri: `https://twitter.com/${user.account.twitter.screenName}`
 			});
 		}
 
@@ -142,7 +142,7 @@ class LineBot extends BotCore {
 
 	public async showUserTimelinePostback(userId: string) {
 		const tl = await require('../../endpoints/users/posts')({
-			user_id: userId,
+			userId: userId,
 			limit: 5
 		}, this.user);
 
@@ -174,7 +174,7 @@ module.exports = async (app: express.Application) => {
 			const user = await User.findOne({
 				host: null,
 				'account.line': {
-					user_id: sourceId
+					userId: sourceId
 				}
 			});
 
@@ -184,7 +184,7 @@ module.exports = async (app: express.Application) => {
 				User.update(user._id, {
 					$set: {
 						'account.line': {
-							user_id: sourceId
+							userId: sourceId
 						}
 					}
 				});
@@ -194,7 +194,7 @@ module.exports = async (app: express.Application) => {
 				User.update(user._id, {
 					$set: {
 						'account.line': {
-							user_id: null
+							userId: null
 						}
 					}
 				});
diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts
new file mode 100644
index 0000000000..6bf5fcbc02
--- /dev/null
+++ b/src/api/common/add-file-to-drive.ts
@@ -0,0 +1,306 @@
+import { Buffer } from 'buffer';
+import * as fs from 'fs';
+import * as tmp from 'tmp';
+import * as stream from 'stream';
+
+import * as mongodb from 'mongodb';
+import * as crypto from 'crypto';
+import * as _gm from 'gm';
+import * as debug from 'debug';
+import fileType = require('file-type');
+import prominence = require('prominence');
+
+import DriveFile, { getGridFSBucket } from '../models/drive-file';
+import DriveFolder from '../models/drive-folder';
+import { pack } from '../models/drive-file';
+import event, { publishDriveStream } from '../event';
+import config from '../../conf';
+
+const gm = _gm.subClass({
+	imageMagick: true
+});
+
+const log = debug('misskey:register-drive-file');
+
+const tmpFile = (): Promise<string> => new Promise((resolve, reject) => {
+	tmp.file((e, path) => {
+		if (e) return reject(e);
+		resolve(path);
+	});
+});
+
+const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise<any> =>
+	getGridFSBucket()
+		.then(bucket => new Promise((resolve, reject) => {
+			const writeStream = bucket.openUploadStream(name, { contentType: type, metadata });
+			writeStream.once('finish', (doc) => { resolve(doc); });
+			writeStream.on('error', reject);
+			readable.pipe(writeStream);
+		}));
+
+const addFile = async (
+	user: any,
+	path: string,
+	name: string = null,
+	comment: string = null,
+	folderId: mongodb.ObjectID = null,
+	force: boolean = false
+) => {
+	log(`registering ${name} (user: ${user.username}, path: ${path})`);
+
+	// Calculate hash, get content type and get file size
+	const [hash, [mime, ext], size] = await Promise.all([
+		// hash
+		((): Promise<string> => new Promise((res, rej) => {
+			const readable = fs.createReadStream(path);
+			const hash = crypto.createHash('md5');
+			const chunks = [];
+			readable
+				.on('error', rej)
+				.pipe(hash)
+				.on('error', rej)
+				.on('data', (chunk) => chunks.push(chunk))
+				.on('end', () => {
+					const buffer = Buffer.concat(chunks);
+					res(buffer.toString('hex'));
+				});
+		}))(),
+		// mime
+		((): Promise<[string, string | null]> => new Promise((res, rej) => {
+			const readable = fs.createReadStream(path);
+			readable
+				.on('error', rej)
+				.once('data', (buffer: Buffer) => {
+					readable.destroy();
+					const type = fileType(buffer);
+					if (type) {
+						return res([type.mime, type.ext]);
+					} else {
+						// 種類が同定できなかったら application/octet-stream にする
+						return res(['application/octet-stream', null]);
+					}
+				});
+		}))(),
+		// size
+		((): Promise<number> => new Promise((res, rej) => {
+			fs.stat(path, (err, stats) => {
+				if (err) return rej(err);
+				res(stats.size);
+			});
+		}))()
+	]);
+
+	log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`);
+
+	// detect name
+	const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled');
+
+	if (!force) {
+		// Check if there is a file with the same hash
+		const much = await DriveFile.findOne({
+			md5: hash,
+			'metadata.userId': user._id
+		});
+
+		if (much !== null) {
+			log('file with same hash is found');
+			return much;
+		} else {
+			log('file with same hash is not found');
+		}
+	}
+
+	const [wh, avgColor, folder] = await Promise.all([
+		// Width and height (when image)
+		(async () => {
+			// 画像かどうか
+			if (!/^image\/.*$/.test(mime)) {
+				return null;
+			}
+
+			const imageType = mime.split('/')[1];
+
+			// 画像でもPNGかJPEGかGIFでないならスキップ
+			if (imageType != 'png' && imageType != 'jpeg' && imageType != 'gif') {
+				return null;
+			}
+
+			log('calculate image width and height...');
+
+			// Calculate width and height
+			const g = gm(fs.createReadStream(path), name);
+			const size = await prominence(g).size();
+
+			log(`image width and height is calculated: ${size.width}, ${size.height}`);
+
+			return [size.width, size.height];
+		})(),
+		// average color (when image)
+		(async () => {
+			// 画像かどうか
+			if (!/^image\/.*$/.test(mime)) {
+				return null;
+			}
+
+			const imageType = mime.split('/')[1];
+
+			// 画像でもPNGかJPEGでないならスキップ
+			if (imageType != 'png' && imageType != 'jpeg') {
+				return null;
+			}
+
+			log('calculate average color...');
+
+			const buffer = await prominence(gm(fs.createReadStream(path), name)
+				.setFormat('ppm')
+				.resize(1, 1)) // 1pxのサイズに縮小して平均色を取得するというハック
+				.toBuffer();
+
+			const r = buffer.readUInt8(buffer.length - 3);
+			const g = buffer.readUInt8(buffer.length - 2);
+			const b = buffer.readUInt8(buffer.length - 1);
+
+			log(`average color is calculated: ${r}, ${g}, ${b}`);
+
+			return [r, g, b];
+		})(),
+		// folder
+		(async () => {
+			if (!folderId) {
+				return null;
+			}
+			const driveFolder = await DriveFolder.findOne({
+				_id: folderId,
+				userId: user._id
+			});
+			if (!driveFolder) {
+				throw 'folder-not-found';
+			}
+			return driveFolder;
+		})(),
+		// usage checker
+		(async () => {
+			// Calculate drive usage
+			const usage = await DriveFile
+				.aggregate([{
+					$match: { 'metadata.userId': user._id }
+				}, {
+					$project: {
+						length: true
+					}
+				}, {
+					$group: {
+						_id: null,
+						usage: { $sum: '$length' }
+					}
+				}])
+				.then((aggregates: any[]) => {
+					if (aggregates.length > 0) {
+						return aggregates[0].usage;
+					}
+					return 0;
+				});
+
+			log(`drive usage is ${usage}`);
+
+			// If usage limit exceeded
+			if (usage + size > user.driveCapacity) {
+				throw 'no-free-space';
+			}
+		})()
+	]);
+
+	const readable = fs.createReadStream(path);
+
+	const properties = {};
+
+	if (wh) {
+		properties['width'] = wh[0];
+		properties['height'] = wh[1];
+	}
+
+	if (avgColor) {
+		properties['avgColor'] = avgColor;
+	}
+
+	return addToGridFS(detectedName, readable, mime, {
+		userId: user._id,
+		folderId: folder !== null ? folder._id : null,
+		comment: comment,
+		properties: properties
+	});
+};
+
+/**
+ * Add file to drive
+ *
+ * @param user User who wish to add file
+ * @param file File path or readableStream
+ * @param comment Comment
+ * @param type File type
+ * @param folderId Folder ID
+ * @param force If set to true, forcibly upload the file even if there is a file with the same hash.
+ * @return Object that represents added file
+ */
+export default (user: any, file: string | stream.Readable, ...args) => new Promise<any>((resolve, reject) => {
+	// Get file path
+	new Promise((res: (v: [string, boolean]) => void, rej) => {
+		if (typeof file === 'string') {
+			res([file, false]);
+			return;
+		}
+		if (typeof file === 'object' && typeof file.read === 'function') {
+			tmpFile()
+				.then(path => {
+					const readable: stream.Readable = file;
+					const writable = fs.createWriteStream(path);
+					readable
+						.on('error', rej)
+						.on('end', () => {
+							res([path, true]);
+						})
+						.pipe(writable)
+						.on('error', rej);
+				})
+				.catch(rej);
+		}
+		rej(new Error('un-compatible file.'));
+	})
+	.then(([path, shouldCleanup]): Promise<any> => new Promise((res, rej) => {
+		addFile(user, path, ...args)
+			.then(file => {
+				res(file);
+				if (shouldCleanup) {
+					fs.unlink(path, (e) => {
+						if (e) log(e.stack);
+					});
+				}
+			})
+			.catch(rej);
+	}))
+	.then(file => {
+		log(`drive file has been created ${file._id}`);
+		resolve(file);
+
+		pack(file).then(serializedFile => {
+			// Publish drive_file_created event
+			event(user._id, 'drive_file_created', serializedFile);
+			publishDriveStream(user._id, 'file_created', serializedFile);
+
+			// Register to search database
+			if (config.elasticsearch.enable) {
+				const es = require('../../db/elasticsearch');
+				es.index({
+					index: 'misskey',
+					type: 'drive_file',
+					id: file._id.toString(),
+					body: {
+						name: file.name,
+						userId: user._id.toString()
+					}
+				});
+			}
+		});
+	})
+	.catch(reject);
+});
diff --git a/src/api/common/drive/add-file.ts b/src/api/common/drive/add-file.ts
index c4f2f212ac..b10f9e381b 100644
--- a/src/api/common/drive/add-file.ts
+++ b/src/api/common/drive/add-file.ts
@@ -100,7 +100,7 @@ const addFile = async (
 		// Check if there is a file with the same hash
 		const much = await DriveFile.findOne({
 			md5: hash,
-			'metadata.user_id': user._id
+			'metadata.userId': user._id
 		});
 
 		if (much !== null) {
@@ -172,7 +172,7 @@ const addFile = async (
 			}
 			const driveFolder = await DriveFolder.findOne({
 				_id: folderId,
-				user_id: user._id
+				userId: user._id
 			});
 			if (!driveFolder) {
 				throw 'folder-not-found';
@@ -184,7 +184,7 @@ const addFile = async (
 			// Calculate drive usage
 			const usage = await DriveFile
 				.aggregate([{
-					$match: { 'metadata.user_id': user._id }
+					$match: { 'metadata.userId': user._id }
 				}, {
 					$project: {
 						length: true
@@ -205,7 +205,7 @@ const addFile = async (
 			log(`drive usage is ${usage}`);
 
 			// If usage limit exceeded
-			if (usage + size > user.drive_capacity) {
+			if (usage + size > user.driveCapacity) {
 				throw 'no-free-space';
 			}
 		})()
@@ -221,12 +221,12 @@ const addFile = async (
 	}
 
 	if (averageColor) {
-		properties['average_color'] = averageColor;
+		properties['avgColor'] = averageColor;
 	}
 
 	return addToGridFS(detectedName, readable, mime, {
-		user_id: user._id,
-		folder_id: folder !== null ? folder._id : null,
+		userId: user._id,
+		folderId: folder !== null ? folder._id : null,
 		comment: comment,
 		properties: properties
 	});
@@ -297,7 +297,7 @@ export default (user: any, file: string | stream.Readable, ...args) => new Promi
 					id: file._id.toString(),
 					body: {
 						name: file.name,
-						user_id: user._id.toString()
+						userId: user._id.toString()
 					}
 				});
 			}
diff --git a/src/api/common/get-friends.ts b/src/api/common/get-friends.ts
index db6313816d..7f548b3bbf 100644
--- a/src/api/common/get-friends.ts
+++ b/src/api/common/get-friends.ts
@@ -6,17 +6,17 @@ export default async (me: mongodb.ObjectID, includeMe: boolean = true) => {
 	// SELECT followee
 	const myfollowing = await Following
 		.find({
-			follower_id: me,
+			followerId: me,
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
+			deletedAt: { $exists: false }
 		}, {
 			fields: {
-				followee_id: true
+				followeeId: true
 			}
 		});
 
 	// ID list of other users who the I follows
-	const myfollowingIds = myfollowing.map(follow => follow.followee_id);
+	const myfollowingIds = myfollowing.map(follow => follow.followeeId);
 
 	if (includeMe) {
 		myfollowingIds.push(me);
diff --git a/src/api/common/notify.ts b/src/api/common/notify.ts
index ae5669b84c..c4df17f880 100644
--- a/src/api/common/notify.ts
+++ b/src/api/common/notify.ts
@@ -16,11 +16,11 @@ export default (
 
 	// Create notification
 	const notification = await Notification.insert(Object.assign({
-		created_at: new Date(),
-		notifiee_id: notifiee,
-		notifier_id: notifier,
+		createdAt: new Date(),
+		notifieeId: notifiee,
+		notifierId: notifier,
 		type: type,
-		is_read: false
+		isRead: false
 	}, content));
 
 	resolve(notification);
@@ -31,14 +31,14 @@ export default (
 
 	// 3秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する
 	setTimeout(async () => {
-		const fresh = await Notification.findOne({ _id: notification._id }, { is_read: true });
-		if (!fresh.is_read) {
+		const fresh = await Notification.findOne({ _id: notification._id }, { isRead: true });
+		if (!fresh.isRead) {
 			//#region ただしミュートしているユーザーからの通知なら無視
 			const mute = await Mute.find({
-				muter_id: notifiee,
-				deleted_at: { $exists: false }
+				muterId: notifiee,
+				deletedAt: { $exists: false }
 			});
-			const mutedUserIds = mute.map(m => m.mutee_id.toString());
+			const mutedUserIds = mute.map(m => m.muteeId.toString());
 			if (mutedUserIds.indexOf(notifier.toString()) != -1) {
 				return;
 			}
diff --git a/src/api/common/push-sw.ts b/src/api/common/push-sw.ts
index 2993c760ee..f90233233f 100644
--- a/src/api/common/push-sw.ts
+++ b/src/api/common/push-sw.ts
@@ -20,7 +20,7 @@ export default async function(userId: mongo.ObjectID | string, type, body?) {
 
 	// Fetch
 	const subscriptions = await Subscription.find({
-		user_id: userId
+		userId: userId
 	});
 
 	subscriptions.forEach(subscription => {
@@ -41,7 +41,7 @@ export default async function(userId: mongo.ObjectID | string, type, body?) {
 
 			if (err.statusCode == 410) {
 				Subscription.remove({
-					user_id: userId,
+					userId: userId,
 					endpoint: subscription.endpoint,
 					auth: subscription.auth,
 					publickey: subscription.publickey
diff --git a/src/api/common/read-messaging-message.ts b/src/api/common/read-messaging-message.ts
index 8e5e5b2b68..9047edec8c 100644
--- a/src/api/common/read-messaging-message.ts
+++ b/src/api/common/read-messaging-message.ts
@@ -37,12 +37,12 @@ export default (
 	// Update documents
 	await Message.update({
 		_id: { $in: ids },
-		user_id: otherpartyId,
-		recipient_id: userId,
-		is_read: false
+		userId: otherpartyId,
+		recipientId: userId,
+		isRead: false
 	}, {
 		$set: {
-			is_read: true
+			isRead: true
 		}
 	}, {
 		multi: true
@@ -55,8 +55,8 @@ export default (
 	// Calc count of my unread messages
 	const count = await Message
 		.count({
-			recipient_id: userId,
-			is_read: false
+			recipientId: userId,
+			isRead: false
 		});
 
 	if (count == 0) {
diff --git a/src/api/common/read-notification.ts b/src/api/common/read-notification.ts
index 3009cc5d08..5bbf136323 100644
--- a/src/api/common/read-notification.ts
+++ b/src/api/common/read-notification.ts
@@ -29,10 +29,10 @@ export default (
 	// Update documents
 	await Notification.update({
 		_id: { $in: ids },
-		is_read: false
+		isRead: false
 	}, {
 		$set: {
-			is_read: true
+			isRead: true
 		}
 	}, {
 		multi: true
@@ -41,8 +41,8 @@ export default (
 	// Calc count of my unread notifications
 	const count = await Notification
 		.count({
-			notifiee_id: userId,
-			is_read: false
+			notifieeId: userId,
+			isRead: false
 		});
 
 	if (count == 0) {
diff --git a/src/api/common/watch-post.ts b/src/api/common/watch-post.ts
index 1a50f0edaa..61ea444430 100644
--- a/src/api/common/watch-post.ts
+++ b/src/api/common/watch-post.ts
@@ -3,15 +3,15 @@ import Watching from '../models/post-watching';
 
 export default async (me: mongodb.ObjectID, post: object) => {
 	// 自分の投稿はwatchできない
-	if (me.equals((post as any).user_id)) {
+	if (me.equals((post as any).userId)) {
 		return;
 	}
 
 	// if watching now
 	const exist = await Watching.findOne({
-		post_id: (post as any)._id,
-		user_id: me,
-		deleted_at: { $exists: false }
+		postId: (post as any)._id,
+		userId: me,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -19,8 +19,8 @@ export default async (me: mongodb.ObjectID, post: object) => {
 	}
 
 	await Watching.insert({
-		created_at: new Date(),
-		post_id: (post as any)._id,
-		user_id: me
+		createdAt: new Date(),
+		postId: (post as any)._id,
+		userId: me
 	});
 };
diff --git a/src/api/endpoints/aggregation/posts.ts b/src/api/endpoints/aggregation/posts.ts
index 9d8bccbdb2..67d2619640 100644
--- a/src/api/endpoints/aggregation/posts.ts
+++ b/src/api/endpoints/aggregation/posts.ts
@@ -18,23 +18,23 @@ module.exports = params => new Promise(async (res, rej) => {
 	const datas = await Post
 		.aggregate([
 			{ $project: {
-				repost_id: '$repost_id',
-				reply_id: '$reply_id',
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				repostId: '$repostId',
+				replyId: '$replyId',
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				},
 				type: {
 					$cond: {
-						if: { $ne: ['$repost_id', null] },
+						if: { $ne: ['$repostId', null] },
 						then: 'repost',
 						else: {
 							$cond: {
-								if: { $ne: ['$reply_id', null] },
+								if: { $ne: ['$replyId', null] },
 								then: 'reply',
 								else: 'post'
 							}
diff --git a/src/api/endpoints/aggregation/posts/reaction.ts b/src/api/endpoints/aggregation/posts/reaction.ts
index eb99b9d088..9f9a4f37ee 100644
--- a/src/api/endpoints/aggregation/posts/reaction.ts
+++ b/src/api/endpoints/aggregation/posts/reaction.ts
@@ -12,9 +12,9 @@ import Reaction from '../../../models/post-reaction';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Lookup post
 	const post = await Post.findOne({
@@ -27,15 +27,15 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const datas = await Reaction
 		.aggregate([
-			{ $match: { post_id: post._id } },
+			{ $match: { postId: post._id } },
 			{ $project: {
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				}
 			}},
 			{ $group: {
diff --git a/src/api/endpoints/aggregation/posts/reactions.ts b/src/api/endpoints/aggregation/posts/reactions.ts
index 790b523be9..2dc989281c 100644
--- a/src/api/endpoints/aggregation/posts/reactions.ts
+++ b/src/api/endpoints/aggregation/posts/reactions.ts
@@ -12,9 +12,9 @@ import Reaction from '../../../models/post-reaction';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Lookup post
 	const post = await Post.findOne({
@@ -29,10 +29,10 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const reactions = await Reaction
 		.find({
-			post_id: post._id,
+			postId: post._id,
 			$or: [
-				{ deleted_at: { $exists: false } },
-				{ deleted_at: { $gt: startTime } }
+				{ deletedAt: { $exists: false } },
+				{ deletedAt: { $gt: startTime } }
 			]
 		}, {
 			sort: {
@@ -40,7 +40,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 			},
 			fields: {
 				_id: false,
-				post_id: false
+				postId: false
 			}
 		});
 
@@ -55,7 +55,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 		// day = day.getTime();
 
 		const count = reactions.filter(r =>
-			r.created_at < day && (r.deleted_at == null || r.deleted_at > day)
+			r.createdAt < day && (r.deletedAt == null || r.deletedAt > day)
 		).length;
 
 		graph.push({
diff --git a/src/api/endpoints/aggregation/posts/reply.ts b/src/api/endpoints/aggregation/posts/reply.ts
index b114c34e1e..3b050582a9 100644
--- a/src/api/endpoints/aggregation/posts/reply.ts
+++ b/src/api/endpoints/aggregation/posts/reply.ts
@@ -11,9 +11,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Lookup post
 	const post = await Post.findOne({
@@ -28,13 +28,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
 		.aggregate([
 			{ $match: { reply: post._id } },
 			{ $project: {
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				}
 			}},
 			{ $group: {
diff --git a/src/api/endpoints/aggregation/posts/repost.ts b/src/api/endpoints/aggregation/posts/repost.ts
index 217159caa7..d9f3e36a07 100644
--- a/src/api/endpoints/aggregation/posts/repost.ts
+++ b/src/api/endpoints/aggregation/posts/repost.ts
@@ -11,9 +11,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Lookup post
 	const post = await Post.findOne({
@@ -26,15 +26,15 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const datas = await Post
 		.aggregate([
-			{ $match: { repost_id: post._id } },
+			{ $match: { repostId: post._id } },
 			{ $project: {
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				}
 			}},
 			{ $group: {
diff --git a/src/api/endpoints/aggregation/users.ts b/src/api/endpoints/aggregation/users.ts
index e38ce92ff9..a4e91a2282 100644
--- a/src/api/endpoints/aggregation/users.ts
+++ b/src/api/endpoints/aggregation/users.ts
@@ -22,8 +22,8 @@ module.exports = params => new Promise(async (res, rej) => {
 			},
 			fields: {
 				_id: false,
-				created_at: true,
-				deleted_at: true
+				createdAt: true,
+				deletedAt: true
 			}
 		});
 
@@ -44,11 +44,11 @@ module.exports = params => new Promise(async (res, rej) => {
 		// day = day.getTime();
 
 		const total = users.filter(u =>
-			u.created_at < dayEnd && (u.deleted_at == null || u.deleted_at > dayEnd)
+			u.createdAt < dayEnd && (u.deletedAt == null || u.deletedAt > dayEnd)
 		).length;
 
 		const created = users.filter(u =>
-			u.created_at < dayEnd && u.created_at > dayStart
+			u.createdAt < dayEnd && u.createdAt > dayStart
 		).length;
 
 		graph.push({
diff --git a/src/api/endpoints/aggregation/users/activity.ts b/src/api/endpoints/aggregation/users/activity.ts
index 102a71d7cb..d477616578 100644
--- a/src/api/endpoints/aggregation/users/activity.ts
+++ b/src/api/endpoints/aggregation/users/activity.ts
@@ -18,9 +18,9 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	const [limit = 365, limitErr] = $(params.limit).optional.number().range(1, 365).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
 	const user = await User.findOne({
@@ -37,25 +37,25 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const datas = await Post
 		.aggregate([
-			{ $match: { user_id: user._id } },
+			{ $match: { userId: user._id } },
 			{ $project: {
-				repost_id: '$repost_id',
-				reply_id: '$reply_id',
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				repostId: '$repostId',
+				replyId: '$replyId',
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				},
 				type: {
 					$cond: {
-						if: { $ne: ['$repost_id', null] },
+						if: { $ne: ['$repostId', null] },
 						then: 'repost',
 						else: {
 							$cond: {
-								if: { $ne: ['$reply_id', null] },
+								if: { $ne: ['$replyId', null] },
 								then: 'reply',
 								else: 'post'
 							}
diff --git a/src/api/endpoints/aggregation/users/followers.ts b/src/api/endpoints/aggregation/users/followers.ts
index 3022b2b002..73a30281b3 100644
--- a/src/api/endpoints/aggregation/users/followers.ts
+++ b/src/api/endpoints/aggregation/users/followers.ts
@@ -12,9 +12,9 @@ import Following from '../../../models/following';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
 	const user = await User.findOne({
@@ -33,17 +33,17 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const following = await Following
 		.find({
-			followee_id: user._id,
+			followeeId: user._id,
 			$or: [
-				{ deleted_at: { $exists: false } },
-				{ deleted_at: { $gt: startTime } }
+				{ deletedAt: { $exists: false } },
+				{ deletedAt: { $gt: startTime } }
 			]
 		}, {
 			_id: false,
-			follower_id: false,
-			followee_id: false
+			followerId: false,
+			followeeId: false
 		}, {
-			sort: { created_at: -1 }
+			sort: { createdAt: -1 }
 		});
 
 	const graph = [];
@@ -57,7 +57,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 		// day = day.getTime();
 
 		const count = following.filter(f =>
-			f.created_at < day && (f.deleted_at == null || f.deleted_at > day)
+			f.createdAt < day && (f.deletedAt == null || f.deletedAt > day)
 		).length;
 
 		graph.push({
diff --git a/src/api/endpoints/aggregation/users/following.ts b/src/api/endpoints/aggregation/users/following.ts
index 92da7e6921..16fc568d59 100644
--- a/src/api/endpoints/aggregation/users/following.ts
+++ b/src/api/endpoints/aggregation/users/following.ts
@@ -12,9 +12,9 @@ import Following from '../../../models/following';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
 	const user = await User.findOne({
@@ -33,17 +33,17 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const following = await Following
 		.find({
-			follower_id: user._id,
+			followerId: user._id,
 			$or: [
-				{ deleted_at: { $exists: false } },
-				{ deleted_at: { $gt: startTime } }
+				{ deletedAt: { $exists: false } },
+				{ deletedAt: { $gt: startTime } }
 			]
 		}, {
 			_id: false,
-			follower_id: false,
-			followee_id: false
+			followerId: false,
+			followeeId: false
 		}, {
-			sort: { created_at: -1 }
+			sort: { createdAt: -1 }
 		});
 
 	const graph = [];
@@ -56,7 +56,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 		day = new Date(day.setHours(23));
 
 		const count = following.filter(f =>
-			f.created_at < day && (f.deleted_at == null || f.deleted_at > day)
+			f.createdAt < day && (f.deletedAt == null || f.deletedAt > day)
 		).length;
 
 		graph.push({
diff --git a/src/api/endpoints/aggregation/users/post.ts b/src/api/endpoints/aggregation/users/post.ts
index c6a75eee39..c988748593 100644
--- a/src/api/endpoints/aggregation/users/post.ts
+++ b/src/api/endpoints/aggregation/users/post.ts
@@ -12,9 +12,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
 	const user = await User.findOne({
@@ -31,25 +31,25 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const datas = await Post
 		.aggregate([
-			{ $match: { user_id: user._id } },
+			{ $match: { userId: user._id } },
 			{ $project: {
-				repost_id: '$repost_id',
-				reply_id: '$reply_id',
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				repostId: '$repostId',
+				replyId: '$replyId',
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				},
 				type: {
 					$cond: {
-						if: { $ne: ['$repost_id', null] },
+						if: { $ne: ['$repostId', null] },
 						then: 'repost',
 						else: {
 							$cond: {
-								if: { $ne: ['$reply_id', null] },
+								if: { $ne: ['$replyId', null] },
 								then: 'reply',
 								else: 'post'
 							}
diff --git a/src/api/endpoints/aggregation/users/reaction.ts b/src/api/endpoints/aggregation/users/reaction.ts
index 0a082ed1b7..60b33e9d1c 100644
--- a/src/api/endpoints/aggregation/users/reaction.ts
+++ b/src/api/endpoints/aggregation/users/reaction.ts
@@ -12,9 +12,9 @@ import Reaction from '../../../models/post-reaction';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Lookup user
 	const user = await User.findOne({
@@ -31,15 +31,15 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	const datas = await Reaction
 		.aggregate([
-			{ $match: { user_id: user._id } },
+			{ $match: { userId: user._id } },
 			{ $project: {
-				created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST
+				createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
 			}},
 			{ $project: {
 				date: {
-					year: { $year: '$created_at' },
-					month: { $month: '$created_at' },
-					day: { $dayOfMonth: '$created_at' }
+					year: { $year: '$createdAt' },
+					month: { $month: '$createdAt' },
+					day: { $dayOfMonth: '$createdAt' }
 				}
 			}},
 			{ $group: {
diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts
index 0f688792a7..cde4846e0f 100644
--- a/src/api/endpoints/app/create.ts
+++ b/src/api/endpoints/app/create.ts
@@ -13,7 +13,7 @@ import App, { isValidNameId, pack } from '../../models/app';
  *     parameters:
  *       - $ref: "#/parameters/AccessToken"
  *       -
- *         name: name_id
+ *         name: nameId
  *         description: Application unique name
  *         in: formData
  *         required: true
@@ -66,9 +66,9 @@ import App, { isValidNameId, pack } from '../../models/app';
  * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
-	// Get 'name_id' parameter
-	const [nameId, nameIdErr] = $(params.name_id).string().pipe(isValidNameId).$;
-	if (nameIdErr) return rej('invalid name_id param');
+	// Get 'nameId' parameter
+	const [nameId, nameIdErr] = $(params.nameId).string().pipe(isValidNameId).$;
+	if (nameIdErr) return rej('invalid nameId param');
 
 	// Get 'name' parameter
 	const [name, nameErr] = $(params.name).string().$;
@@ -92,11 +92,11 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	// Create account
 	const app = await App.insert({
-		created_at: new Date(),
-		user_id: user._id,
+		createdAt: new Date(),
+		userId: user._id,
 		name: name,
-		name_id: nameId,
-		name_id_lower: nameId.toLowerCase(),
+		nameId: nameId,
+		nameIdLower: nameId.toLowerCase(),
 		description: description,
 		permission: permission,
 		callback_url: callbackUrl,
diff --git a/src/api/endpoints/app/name_id/available.ts b/src/api/endpoints/app/name_id/available.ts
index 3d2c710322..6d02b26d2b 100644
--- a/src/api/endpoints/app/name_id/available.ts
+++ b/src/api/endpoints/app/name_id/available.ts
@@ -7,12 +7,12 @@ import { isValidNameId } from '../../../models/app';
 
 /**
  * @swagger
- * /app/name_id/available:
+ * /app/nameId/available:
  *   post:
- *     summary: Check available name_id on creation an application
+ *     summary: Check available nameId on creation an application
  *     parameters:
  *       -
- *         name: name_id
+ *         name: nameId
  *         description: Application unique name
  *         in: formData
  *         required: true
@@ -25,7 +25,7 @@ import { isValidNameId } from '../../../models/app';
  *           type: object
  *           properties:
  *             available:
- *               description: Whether name_id is available
+ *               description: Whether nameId is available
  *               type: boolean
  *
  *       default:
@@ -35,20 +35,20 @@ import { isValidNameId } from '../../../models/app';
  */
 
 /**
- * Check available name_id of app
+ * Check available nameId of app
  *
  * @param {any} params
  * @return {Promise<any>}
  */
 module.exports = async (params) => new Promise(async (res, rej) => {
-	// Get 'name_id' parameter
-	const [nameId, nameIdErr] = $(params.name_id).string().pipe(isValidNameId).$;
-	if (nameIdErr) return rej('invalid name_id param');
+	// Get 'nameId' parameter
+	const [nameId, nameIdErr] = $(params.nameId).string().pipe(isValidNameId).$;
+	if (nameIdErr) return rej('invalid nameId param');
 
 	// Get exist
 	const exist = await App
 		.count({
-			name_id_lower: nameId.toLowerCase()
+			nameIdLower: nameId.toLowerCase()
 		}, {
 			limit: 1
 		});
diff --git a/src/api/endpoints/app/show.ts b/src/api/endpoints/app/show.ts
index 8bc3dda42c..34bb958eee 100644
--- a/src/api/endpoints/app/show.ts
+++ b/src/api/endpoints/app/show.ts
@@ -9,15 +9,15 @@ import App, { pack } from '../../models/app';
  * /app/show:
  *   post:
  *     summary: Show an application's information
- *     description: Require app_id or name_id
+ *     description: Require appId or nameId
  *     parameters:
  *       -
- *         name: app_id
+ *         name: appId
  *         description: Application ID
  *         in: formData
  *         type: string
  *       -
- *         name: name_id
+ *         name: nameId
  *         description: Application unique name
  *         in: formData
  *         type: string
@@ -44,22 +44,22 @@ import App, { pack } from '../../models/app';
  * @return {Promise<any>}
  */
 module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => {
-	// Get 'app_id' parameter
-	const [appId, appIdErr] = $(params.app_id).optional.id().$;
-	if (appIdErr) return rej('invalid app_id param');
+	// Get 'appId' parameter
+	const [appId, appIdErr] = $(params.appId).optional.id().$;
+	if (appIdErr) return rej('invalid appId param');
 
-	// Get 'name_id' parameter
-	const [nameId, nameIdErr] = $(params.name_id).optional.string().$;
-	if (nameIdErr) return rej('invalid name_id param');
+	// Get 'nameId' parameter
+	const [nameId, nameIdErr] = $(params.nameId).optional.string().$;
+	if (nameIdErr) return rej('invalid nameId param');
 
 	if (appId === undefined && nameId === undefined) {
-		return rej('app_id or name_id is required');
+		return rej('appId or nameId is required');
 	}
 
 	// Lookup app
 	const app = appId !== undefined
 		? await App.findOne({ _id: appId })
-		: await App.findOne({ name_id_lower: nameId.toLowerCase() });
+		: await App.findOne({ nameIdLower: nameId.toLowerCase() });
 
 	if (app === null) {
 		return rej('app not found');
@@ -67,6 +67,6 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) =>
 
 	// Send response
 	res(await pack(app, user, {
-		includeSecret: isSecure && app.user_id.equals(user._id)
+		includeSecret: isSecure && app.userId.equals(user._id)
 	}));
 });
diff --git a/src/api/endpoints/auth/accept.ts b/src/api/endpoints/auth/accept.ts
index 4ee20a6d25..5a1925144d 100644
--- a/src/api/endpoints/auth/accept.ts
+++ b/src/api/endpoints/auth/accept.ts
@@ -56,14 +56,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Fetch exist access token
 	const exist = await AccessToken.findOne({
-		app_id: session.app_id,
-		user_id: user._id,
+		appId: session.appId,
+		userId: user._id,
 	});
 
 	if (exist === null) {
 		// Lookup app
 		const app = await App.findOne({
-			_id: session.app_id
+			_id: session.appId
 		});
 
 		// Generate Hash
@@ -73,9 +73,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 		// Insert access token doc
 		await AccessToken.insert({
-			created_at: new Date(),
-			app_id: session.app_id,
-			user_id: user._id,
+			createdAt: new Date(),
+			appId: session.appId,
+			userId: user._id,
 			token: accessToken,
 			hash: hash
 		});
@@ -84,7 +84,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Update session
 	await AuthSess.update(session._id, {
 		$set: {
-			user_id: user._id
+			userId: user._id
 		}
 	});
 
diff --git a/src/api/endpoints/auth/session/generate.ts b/src/api/endpoints/auth/session/generate.ts
index 510382247e..81db188ee5 100644
--- a/src/api/endpoints/auth/session/generate.ts
+++ b/src/api/endpoints/auth/session/generate.ts
@@ -63,8 +63,8 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	// Create session token document
 	const doc = await AuthSess.insert({
-		created_at: new Date(),
-		app_id: app._id,
+		createdAt: new Date(),
+		appId: app._id,
 		token: token
 	});
 
diff --git a/src/api/endpoints/auth/session/show.ts b/src/api/endpoints/auth/session/show.ts
index 73ac3185f6..869b714e71 100644
--- a/src/api/endpoints/auth/session/show.ts
+++ b/src/api/endpoints/auth/session/show.ts
@@ -23,17 +23,17 @@ import AuthSess, { pack } from '../../../models/auth-session';
  *         schema:
  *           type: object
  *           properties:
- *             created_at:
+ *             createdAt:
  *               type: string
  *               format: date-time
  *               description: Date and time of the session creation
- *             app_id:
+ *             appId:
  *               type: string
  *               description: Application ID
  *             token:
  *               type: string
  *               description: Session Token
- *             user_id:
+ *             userId:
  *               type: string
  *               description: ID of user who create the session
  *             app:
diff --git a/src/api/endpoints/auth/session/userkey.ts b/src/api/endpoints/auth/session/userkey.ts
index fc989bf8c2..74f025c8a5 100644
--- a/src/api/endpoints/auth/session/userkey.ts
+++ b/src/api/endpoints/auth/session/userkey.ts
@@ -71,21 +71,21 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	const session = await AuthSess
 		.findOne({
 			token: token,
-			app_id: app._id
+			appId: app._id
 		});
 
 	if (session === null) {
 		return rej('session not found');
 	}
 
-	if (session.user_id == null) {
+	if (session.userId == null) {
 		return rej('this session is not allowed yet');
 	}
 
 	// Lookup access token
 	const accessToken = await AccessToken.findOne({
-		app_id: app._id,
-		user_id: session.user_id
+		appId: app._id,
+		userId: session.userId
 	});
 
 	// Delete session
@@ -101,8 +101,8 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	// Response
 	res({
-		access_token: accessToken.token,
-		user: await pack(session.user_id, null, {
+		accessToken: accessToken.token,
+		user: await pack(session.userId, null, {
 			detail: true
 		})
 	});
diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts
index 695b4515b3..1dc453c4a5 100644
--- a/src/api/endpoints/channels/create.ts
+++ b/src/api/endpoints/channels/create.ts
@@ -20,11 +20,11 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	// Create a channel
 	const channel = await Channel.insert({
-		created_at: new Date(),
-		user_id: user._id,
+		createdAt: new Date(),
+		userId: user._id,
 		title: title,
 		index: 0,
-		watching_count: 1
+		watchingCount: 1
 	});
 
 	// Response
@@ -32,8 +32,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	// Create Watching
 	await Watching.insert({
-		created_at: new Date(),
-		user_id: user._id,
-		channel_id: channel._id
+		createdAt: new Date(),
+		userId: user._id,
+		channelId: channel._id
 	});
 });
diff --git a/src/api/endpoints/channels/posts.ts b/src/api/endpoints/channels/posts.ts
index d722589c20..7536664051 100644
--- a/src/api/endpoints/channels/posts.ts
+++ b/src/api/endpoints/channels/posts.ts
@@ -30,9 +30,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		return rej('cannot set since_id and until_id');
 	}
 
-	// Get 'channel_id' parameter
-	const [channelId, channelIdErr] = $(params.channel_id).id().$;
-	if (channelIdErr) return rej('invalid channel_id param');
+	// Get 'channelId' parameter
+	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	if (channelIdErr) return rej('invalid channelId param');
 
 	// Fetch channel
 	const channel: IChannel = await Channel.findOne({
@@ -49,7 +49,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	};
 
 	const query = {
-		channel_id: channel._id
+		channelId: channel._id
 	} as any;
 
 	if (sinceId) {
diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts
index 332da64675..5874ed18a6 100644
--- a/src/api/endpoints/channels/show.ts
+++ b/src/api/endpoints/channels/show.ts
@@ -12,9 +12,9 @@ import Channel, { IChannel, pack } from '../../models/channel';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'channel_id' parameter
-	const [channelId, channelIdErr] = $(params.channel_id).id().$;
-	if (channelIdErr) return rej('invalid channel_id param');
+	// Get 'channelId' parameter
+	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	if (channelIdErr) return rej('invalid channelId param');
 
 	// Fetch channel
 	const channel: IChannel = await Channel.findOne({
diff --git a/src/api/endpoints/channels/unwatch.ts b/src/api/endpoints/channels/unwatch.ts
index 19d3be118a..709313bc6e 100644
--- a/src/api/endpoints/channels/unwatch.ts
+++ b/src/api/endpoints/channels/unwatch.ts
@@ -13,9 +13,9 @@ import Watching from '../../models/channel-watching';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'channel_id' parameter
-	const [channelId, channelIdErr] = $(params.channel_id).id().$;
-	if (channelIdErr) return rej('invalid channel_id param');
+	// Get 'channelId' parameter
+	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	if (channelIdErr) return rej('invalid channelId param');
 
 	//#region Fetch channel
 	const channel = await Channel.findOne({
@@ -29,9 +29,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	//#region Check whether not watching
 	const exist = await Watching.findOne({
-		user_id: user._id,
-		channel_id: channel._id,
-		deleted_at: { $exists: false }
+		userId: user._id,
+		channelId: channel._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist === null) {
@@ -44,7 +44,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: exist._id
 	}, {
 		$set: {
-			deleted_at: new Date()
+			deletedAt: new Date()
 		}
 	});
 
@@ -54,7 +54,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Decrement watching count
 	Channel.update(channel._id, {
 		$inc: {
-			watching_count: -1
+			watchingCount: -1
 		}
 	});
 });
diff --git a/src/api/endpoints/channels/watch.ts b/src/api/endpoints/channels/watch.ts
index 030e0dd411..df9e70d5c2 100644
--- a/src/api/endpoints/channels/watch.ts
+++ b/src/api/endpoints/channels/watch.ts
@@ -13,9 +13,9 @@ import Watching from '../../models/channel-watching';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'channel_id' parameter
-	const [channelId, channelIdErr] = $(params.channel_id).id().$;
-	if (channelIdErr) return rej('invalid channel_id param');
+	// Get 'channelId' parameter
+	const [channelId, channelIdErr] = $(params.channelId).id().$;
+	if (channelIdErr) return rej('invalid channelId param');
 
 	//#region Fetch channel
 	const channel = await Channel.findOne({
@@ -29,9 +29,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	//#region Check whether already watching
 	const exist = await Watching.findOne({
-		user_id: user._id,
-		channel_id: channel._id,
-		deleted_at: { $exists: false }
+		userId: user._id,
+		channelId: channel._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -41,9 +41,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create Watching
 	await Watching.insert({
-		created_at: new Date(),
-		user_id: user._id,
-		channel_id: channel._id
+		createdAt: new Date(),
+		userId: user._id,
+		channelId: channel._id
 	});
 
 	// Send response
@@ -52,7 +52,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Increment watching count
 	Channel.update(channel._id, {
 		$inc: {
-			watching_count: 1
+			watchingCount: 1
 		}
 	});
 });
diff --git a/src/api/endpoints/drive.ts b/src/api/endpoints/drive.ts
index d92473633a..eb21853916 100644
--- a/src/api/endpoints/drive.ts
+++ b/src/api/endpoints/drive.ts
@@ -14,7 +14,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Calculate drive usage
 	const usage = ((await DriveFile
 		.aggregate([
-			{ $match: { 'metadata.user_id': user._id } },
+			{ $match: { 'metadata.userId': user._id } },
 			{
 				$project: {
 					length: true
@@ -31,7 +31,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		}).usage;
 
 	res({
-		capacity: user.drive_capacity,
+		capacity: user.driveCapacity,
 		usage: usage
 	});
 });
diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts
index 89915331ea..1ce855932b 100644
--- a/src/api/endpoints/drive/files.ts
+++ b/src/api/endpoints/drive/files.ts
@@ -30,9 +30,9 @@ module.exports = async (params, user, app) => {
 		throw 'cannot set since_id and until_id';
 	}
 
-	// Get 'folder_id' parameter
-	const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) throw 'invalid folder_id param';
+	// Get 'folderId' parameter
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) throw 'invalid folderId param';
 
 	// Get 'type' parameter
 	const [type, typeErr] = $(params.type).optional.string().match(/^[a-zA-Z\/\-\*]+$/).$;
@@ -43,8 +43,8 @@ module.exports = async (params, user, app) => {
 		_id: -1
 	};
 	const query = {
-		'metadata.user_id': user._id,
-		'metadata.folder_id': folderId
+		'metadata.userId': user._id,
+		'metadata.folderId': folderId
 	} as any;
 	if (sinceId) {
 		sort._id = 1;
diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts
index db801b61fe..2cd89a8fac 100644
--- a/src/api/endpoints/drive/files/create.ts
+++ b/src/api/endpoints/drive/files/create.ts
@@ -33,9 +33,9 @@ module.exports = async (file, params, user): Promise<any> => {
 		name = null;
 	}
 
-	// Get 'folder_id' parameter
-	const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) throw 'invalid folder_id param';
+	// Get 'folderId' parameter
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) throw 'invalid folderId param';
 
 	try {
 		// Create file
diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts
index e026afe936..47ce891305 100644
--- a/src/api/endpoints/drive/files/find.ts
+++ b/src/api/endpoints/drive/files/find.ts
@@ -16,16 +16,16 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [name, nameErr] = $(params.name).string().$;
 	if (nameErr) return rej('invalid name param');
 
-	// Get 'folder_id' parameter
-	const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) return rej('invalid folder_id param');
+	// Get 'folderId' parameter
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) return rej('invalid folderId param');
 
 	// Issue query
 	const files = await DriveFile
 		.find({
 			filename: name,
-			'metadata.user_id': user._id,
-			'metadata.folder_id': folderId
+			'metadata.userId': user._id,
+			'metadata.folderId': folderId
 		});
 
 	// Serialize
diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts
index 21664f7ba4..63920db7fc 100644
--- a/src/api/endpoints/drive/files/show.ts
+++ b/src/api/endpoints/drive/files/show.ts
@@ -12,15 +12,15 @@ import DriveFile, { pack } from '../../../models/drive-file';
  * @return {Promise<any>}
  */
 module.exports = async (params, user) => {
-	// Get 'file_id' parameter
-	const [fileId, fileIdErr] = $(params.file_id).id().$;
-	if (fileIdErr) throw 'invalid file_id param';
+	// Get 'fileId' parameter
+	const [fileId, fileIdErr] = $(params.fileId).id().$;
+	if (fileIdErr) throw 'invalid fileId param';
 
 	// Fetch file
 	const file = await DriveFile
 		.findOne({
 			_id: fileId,
-			'metadata.user_id': user._id
+			'metadata.userId': user._id
 		});
 
 	if (file === null) {
diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts
index 83da462113..bfad45b0a2 100644
--- a/src/api/endpoints/drive/files/update.ts
+++ b/src/api/endpoints/drive/files/update.ts
@@ -14,15 +14,15 @@ import { publishDriveStream } from '../../../event';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'file_id' parameter
-	const [fileId, fileIdErr] = $(params.file_id).id().$;
-	if (fileIdErr) return rej('invalid file_id param');
+	// Get 'fileId' parameter
+	const [fileId, fileIdErr] = $(params.fileId).id().$;
+	if (fileIdErr) return rej('invalid fileId param');
 
 	// Fetch file
 	const file = await DriveFile
 		.findOne({
 			_id: fileId,
-			'metadata.user_id': user._id
+			'metadata.userId': user._id
 		});
 
 	if (file === null) {
@@ -34,33 +34,33 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (nameErr) return rej('invalid name param');
 	if (name) file.filename = name;
 
-	// Get 'folder_id' parameter
-	const [folderId, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) return rej('invalid folder_id param');
+	// Get 'folderId' parameter
+	const [folderId, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) return rej('invalid folderId param');
 
 	if (folderId !== undefined) {
 		if (folderId === null) {
-			file.metadata.folder_id = null;
+			file.metadata.folderId = null;
 		} else {
 			// Fetch folder
 			const folder = await DriveFolder
 				.findOne({
 					_id: folderId,
-					user_id: user._id
+					userId: user._id
 				});
 
 			if (folder === null) {
 				return rej('folder-not-found');
 			}
 
-			file.metadata.folder_id = folder._id;
+			file.metadata.folderId = folder._id;
 		}
 	}
 
 	await DriveFile.update(file._id, {
 		$set: {
 			filename: file.filename,
-			'metadata.folder_id': file.metadata.folder_id
+			'metadata.folderId': file.metadata.folderId
 		}
 	});
 
diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts
index 346633c616..1a4ce0bf08 100644
--- a/src/api/endpoints/drive/files/upload_from_url.ts
+++ b/src/api/endpoints/drive/files/upload_from_url.ts
@@ -18,9 +18,9 @@ module.exports = async (params, user): Promise<any> => {
 	const [url, urlErr] = $(params.url).string().$;
 	if (urlErr) throw 'invalid url param';
 
-	// Get 'folder_id' parameter
-	const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) throw 'invalid folder_id param';
+	// Get 'folderId' parameter
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) throw 'invalid folderId param';
 
 	return pack(await uploadFromUrl(url, user, folderId));
 };
diff --git a/src/api/endpoints/drive/folders.ts b/src/api/endpoints/drive/folders.ts
index 428bde3507..c259646352 100644
--- a/src/api/endpoints/drive/folders.ts
+++ b/src/api/endpoints/drive/folders.ts
@@ -30,17 +30,17 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 		return rej('cannot set since_id and until_id');
 	}
 
-	// Get 'folder_id' parameter
-	const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$;
-	if (folderIdErr) return rej('invalid folder_id param');
+	// Get 'folderId' parameter
+	const [folderId = null, folderIdErr] = $(params.folderId).optional.nullable.id().$;
+	if (folderIdErr) return rej('invalid folderId param');
 
 	// Construct query
 	const sort = {
 		_id: -1
 	};
 	const query = {
-		user_id: user._id,
-		parent_id: folderId
+		userId: user._id,
+		parentId: folderId
 	} as any;
 	if (sinceId) {
 		sort._id = 1;
diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts
index 03f396ddc9..564558606d 100644
--- a/src/api/endpoints/drive/folders/create.ts
+++ b/src/api/endpoints/drive/folders/create.ts
@@ -17,9 +17,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [name = '無題のフォルダー', nameErr] = $(params.name).optional.string().pipe(isValidFolderName).$;
 	if (nameErr) return rej('invalid name param');
 
-	// Get 'parent_id' parameter
-	const [parentId = null, parentIdErr] = $(params.parent_id).optional.nullable.id().$;
-	if (parentIdErr) return rej('invalid parent_id param');
+	// Get 'parentId' parameter
+	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	if (parentIdErr) return rej('invalid parentId param');
 
 	// If the parent folder is specified
 	let parent = null;
@@ -28,7 +28,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		parent = await DriveFolder
 			.findOne({
 				_id: parentId,
-				user_id: user._id
+				userId: user._id
 			});
 
 		if (parent === null) {
@@ -38,10 +38,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create folder
 	const folder = await DriveFolder.insert({
-		created_at: new Date(),
+		createdAt: new Date(),
 		name: name,
-		parent_id: parent !== null ? parent._id : null,
-		user_id: user._id
+		parentId: parent !== null ? parent._id : null,
+		userId: user._id
 	});
 
 	// Serialize
diff --git a/src/api/endpoints/drive/folders/find.ts b/src/api/endpoints/drive/folders/find.ts
index fc84766bc8..f46aaedd32 100644
--- a/src/api/endpoints/drive/folders/find.ts
+++ b/src/api/endpoints/drive/folders/find.ts
@@ -16,16 +16,16 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [name, nameErr] = $(params.name).string().$;
 	if (nameErr) return rej('invalid name param');
 
-	// Get 'parent_id' parameter
-	const [parentId = null, parentIdErr] = $(params.parent_id).optional.nullable.id().$;
-	if (parentIdErr) return rej('invalid parent_id param');
+	// Get 'parentId' parameter
+	const [parentId = null, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	if (parentIdErr) return rej('invalid parentId param');
 
 	// Issue query
 	const folders = await DriveFolder
 		.find({
 			name: name,
-			user_id: user._id,
-			parent_id: parentId
+			userId: user._id,
+			parentId: parentId
 		});
 
 	// Serialize
diff --git a/src/api/endpoints/drive/folders/show.ts b/src/api/endpoints/drive/folders/show.ts
index e07d14d20d..a6d7e86df1 100644
--- a/src/api/endpoints/drive/folders/show.ts
+++ b/src/api/endpoints/drive/folders/show.ts
@@ -12,15 +12,15 @@ import DriveFolder, { pack } from '../../../models/drive-folder';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'folder_id' parameter
-	const [folderId, folderIdErr] = $(params.folder_id).id().$;
-	if (folderIdErr) return rej('invalid folder_id param');
+	// Get 'folderId' parameter
+	const [folderId, folderIdErr] = $(params.folderId).id().$;
+	if (folderIdErr) return rej('invalid folderId param');
 
 	// Get folder
 	const folder = await DriveFolder
 		.findOne({
 			_id: folderId,
-			user_id: user._id
+			userId: user._id
 		});
 
 	if (folder === null) {
diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts
index d3df8bdae5..fcfd241241 100644
--- a/src/api/endpoints/drive/folders/update.ts
+++ b/src/api/endpoints/drive/folders/update.ts
@@ -13,15 +13,15 @@ import { publishDriveStream } from '../../../event';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'folder_id' parameter
-	const [folderId, folderIdErr] = $(params.folder_id).id().$;
-	if (folderIdErr) return rej('invalid folder_id param');
+	// Get 'folderId' parameter
+	const [folderId, folderIdErr] = $(params.folderId).id().$;
+	if (folderIdErr) return rej('invalid folderId param');
 
 	// Fetch folder
 	const folder = await DriveFolder
 		.findOne({
 			_id: folderId,
-			user_id: user._id
+			userId: user._id
 		});
 
 	if (folder === null) {
@@ -33,18 +33,18 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (nameErr) return rej('invalid name param');
 	if (name) folder.name = name;
 
-	// Get 'parent_id' parameter
-	const [parentId, parentIdErr] = $(params.parent_id).optional.nullable.id().$;
-	if (parentIdErr) return rej('invalid parent_id param');
+	// Get 'parentId' parameter
+	const [parentId, parentIdErr] = $(params.parentId).optional.nullable.id().$;
+	if (parentIdErr) return rej('invalid parentId param');
 	if (parentId !== undefined) {
 		if (parentId === null) {
-			folder.parent_id = null;
+			folder.parentId = null;
 		} else {
 			// Get parent folder
 			const parent = await DriveFolder
 				.findOne({
 					_id: parentId,
-					user_id: user._id
+					userId: user._id
 				});
 
 			if (parent === null) {
@@ -58,25 +58,25 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 					_id: folderId
 				}, {
 					_id: true,
-					parent_id: true
+					parentId: true
 				});
 
 				if (folder2._id.equals(folder._id)) {
 					return true;
-				} else if (folder2.parent_id) {
-					return await checkCircle(folder2.parent_id);
+				} else if (folder2.parentId) {
+					return await checkCircle(folder2.parentId);
 				} else {
 					return false;
 				}
 			}
 
-			if (parent.parent_id !== null) {
-				if (await checkCircle(parent.parent_id)) {
+			if (parent.parentId !== null) {
+				if (await checkCircle(parent.parentId)) {
 					return rej('detected-circular-definition');
 				}
 			}
 
-			folder.parent_id = parent._id;
+			folder.parentId = parent._id;
 		}
 	}
 
@@ -84,7 +84,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	DriveFolder.update(folder._id, {
 		$set: {
 			name: folder.name,
-			parent_id: folder.parent_id
+			parentId: folder.parentId
 		}
 	});
 
diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts
index 8352c7dd4c..0f9cea9f1d 100644
--- a/src/api/endpoints/drive/stream.ts
+++ b/src/api/endpoints/drive/stream.ts
@@ -38,7 +38,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: -1
 	};
 	const query = {
-		'metadata.user_id': user._id
+		'metadata.userId': user._id
 	} as any;
 	if (sinceId) {
 		sort._id = 1;
diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts
index 767b837b35..983d8040f9 100644
--- a/src/api/endpoints/following/create.ts
+++ b/src/api/endpoints/following/create.ts
@@ -17,9 +17,9 @@ import event from '../../event';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// 自分自身
 	if (user._id.equals(userId)) {
@@ -42,9 +42,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Check if already following
 	const exist = await Following.findOne({
-		follower_id: follower._id,
-		followee_id: followee._id,
-		deleted_at: { $exists: false }
+		followerId: follower._id,
+		followeeId: followee._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -53,9 +53,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create following
 	await Following.insert({
-		created_at: new Date(),
-		follower_id: follower._id,
-		followee_id: followee._id
+		createdAt: new Date(),
+		followerId: follower._id,
+		followeeId: followee._id
 	});
 
 	// Send response
@@ -64,14 +64,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Increment following count
 	User.update(follower._id, {
 		$inc: {
-			following_count: 1
+			followingCount: 1
 		}
 	});
 
 	// Increment followers count
 	User.update({ _id: followee._id }, {
 		$inc: {
-			followers_count: 1
+			followersCount: 1
 		}
 	});
 
diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts
index 64b9a8cecb..25eba8b262 100644
--- a/src/api/endpoints/following/delete.ts
+++ b/src/api/endpoints/following/delete.ts
@@ -16,9 +16,9 @@ import event from '../../event';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const follower = user;
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Check if the followee is yourself
 	if (user._id.equals(userId)) {
@@ -41,9 +41,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Check not following
 	const exist = await Following.findOne({
-		follower_id: follower._id,
-		followee_id: followee._id,
-		deleted_at: { $exists: false }
+		followerId: follower._id,
+		followeeId: followee._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist === null) {
@@ -55,7 +55,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: exist._id
 	}, {
 		$set: {
-			deleted_at: new Date()
+			deletedAt: new Date()
 		}
 	});
 
@@ -65,14 +65,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Decrement following count
 	User.update({ _id: follower._id }, {
 		$inc: {
-			following_count: -1
+			followingCount: -1
 		}
 	});
 
 	// Decrement followers count
 	User.update({ _id: followee._id }, {
 		$inc: {
-			followers_count: -1
+			followersCount: -1
 		}
 	});
 
diff --git a/src/api/endpoints/i.ts b/src/api/endpoints/i.ts
index 32b0382faf..f5e92b4ded 100644
--- a/src/api/endpoints/i.ts
+++ b/src/api/endpoints/i.ts
@@ -22,7 +22,7 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) =>
 	// Update lastUsedAt
 	User.update({ _id: user._id }, {
 		$set: {
-			'account.last_used_at': new Date()
+			'account.lastUsedAt': new Date()
 		}
 	});
 });
diff --git a/src/api/endpoints/i/2fa/done.ts b/src/api/endpoints/i/2fa/done.ts
index 0f1db73829..d61ebbe6f9 100644
--- a/src/api/endpoints/i/2fa/done.ts
+++ b/src/api/endpoints/i/2fa/done.ts
@@ -12,12 +12,12 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	const _token = token.replace(/\s/g, '');
 
-	if (user.two_factor_temp_secret == null) {
+	if (user.twoFactorTempSecret == null) {
 		return rej('二段階認証の設定が開始されていません');
 	}
 
 	const verified = (speakeasy as any).totp.verify({
-		secret: user.two_factor_temp_secret,
+		secret: user.twoFactorTempSecret,
 		encoding: 'base32',
 		token: _token
 	});
@@ -28,8 +28,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			'account.two_factor_secret': user.two_factor_temp_secret,
-			'account.two_factor_enabled': true
+			'account.twoFactorSecret': user.twoFactorTempSecret,
+			'account.twoFactorEnabled': true
 		}
 	});
 
diff --git a/src/api/endpoints/i/2fa/register.ts b/src/api/endpoints/i/2fa/register.ts
index 24abfcdfc5..b498a2414e 100644
--- a/src/api/endpoints/i/2fa/register.ts
+++ b/src/api/endpoints/i/2fa/register.ts
@@ -27,7 +27,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			two_factor_temp_secret: secret.base32
+			twoFactorTempSecret: secret.base32
 		}
 	});
 
diff --git a/src/api/endpoints/i/2fa/unregister.ts b/src/api/endpoints/i/2fa/unregister.ts
index c43f9ccc44..0221ecb96d 100644
--- a/src/api/endpoints/i/2fa/unregister.ts
+++ b/src/api/endpoints/i/2fa/unregister.ts
@@ -19,8 +19,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			'account.two_factor_secret': null,
-			'account.two_factor_enabled': false
+			'account.twoFactorSecret': null,
+			'account.twoFactorEnabled': false
 		}
 	});
 
diff --git a/src/api/endpoints/i/appdata/get.ts b/src/api/endpoints/i/appdata/get.ts
index 571208d46c..0b34643f75 100644
--- a/src/api/endpoints/i/appdata/get.ts
+++ b/src/api/endpoints/i/appdata/get.ts
@@ -25,8 +25,8 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 		select[`data.${key}`] = true;
 	}
 	const appdata = await Appdata.findOne({
-		app_id: app._id,
-		user_id: user._id
+		appId: app._id,
+		userId: user._id
 	}, {
 		fields: select
 	});
diff --git a/src/api/endpoints/i/appdata/set.ts b/src/api/endpoints/i/appdata/set.ts
index 2804a14cb3..1e3232ce3d 100644
--- a/src/api/endpoints/i/appdata/set.ts
+++ b/src/api/endpoints/i/appdata/set.ts
@@ -43,11 +43,11 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	}
 
 	await Appdata.update({
-		app_id: app._id,
-		user_id: user._id
+		appId: app._id,
+		userId: user._id
 	}, Object.assign({
-		app_id: app._id,
-		user_id: user._id
+		appId: app._id,
+		userId: user._id
 	}, {
 			$set: set
 		}), {
diff --git a/src/api/endpoints/i/authorized_apps.ts b/src/api/endpoints/i/authorized_apps.ts
index 40ce7a68c8..5a38d7c18f 100644
--- a/src/api/endpoints/i/authorized_apps.ts
+++ b/src/api/endpoints/i/authorized_apps.ts
@@ -28,7 +28,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get tokens
 	const tokens = await AccessToken
 		.find({
-			user_id: user._id
+			userId: user._id
 		}, {
 			limit: limit,
 			skip: offset,
@@ -39,5 +39,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Serialize
 	res(await Promise.all(tokens.map(async token =>
-		await pack(token.app_id))));
+		await pack(token.appId))));
 });
diff --git a/src/api/endpoints/i/favorites.ts b/src/api/endpoints/i/favorites.ts
index eb464cf0f0..22a4399540 100644
--- a/src/api/endpoints/i/favorites.ts
+++ b/src/api/endpoints/i/favorites.ts
@@ -28,7 +28,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Get favorites
 	const favorites = await Favorite
 		.find({
-			user_id: user._id
+			userId: user._id
 		}, {
 			limit: limit,
 			skip: offset,
diff --git a/src/api/endpoints/i/notifications.ts b/src/api/endpoints/i/notifications.ts
index 688039a0dd..e3447c17ec 100644
--- a/src/api/endpoints/i/notifications.ts
+++ b/src/api/endpoints/i/notifications.ts
@@ -47,15 +47,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	const mute = await Mute.find({
-		muter_id: user._id,
-		deleted_at: { $exists: false }
+		muterId: user._id,
+		deletedAt: { $exists: false }
 	});
 
 	const query = {
-		notifiee_id: user._id,
+		notifieeId: user._id,
 		$and: [{
-			notifier_id: {
-				$nin: mute.map(m => m.mutee_id)
+			notifierId: {
+				$nin: mute.map(m => m.muteeId)
 			}
 		}]
 	} as any;
@@ -69,7 +69,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		const followingIds = await getFriends(user._id);
 
 		query.$and.push({
-			notifier_id: {
+			notifierId: {
 				$in: followingIds
 			}
 		});
diff --git a/src/api/endpoints/i/pin.ts b/src/api/endpoints/i/pin.ts
index ff546fc2bd..886a3edeb5 100644
--- a/src/api/endpoints/i/pin.ts
+++ b/src/api/endpoints/i/pin.ts
@@ -14,14 +14,14 @@ import { pack } from '../../models/user';
  * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Fetch pinee
 	const post = await Post.findOne({
 		_id: postId,
-		user_id: user._id
+		userId: user._id
 	});
 
 	if (post === null) {
@@ -30,7 +30,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			pinned_post_id: post._id
+			pinnedPostId: post._id
 		}
 	});
 
diff --git a/src/api/endpoints/i/signin_history.ts b/src/api/endpoints/i/signin_history.ts
index 859e81653d..5b794d0a4b 100644
--- a/src/api/endpoints/i/signin_history.ts
+++ b/src/api/endpoints/i/signin_history.ts
@@ -30,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	const query = {
-		user_id: user._id
+		userId: user._id
 	} as any;
 
 	const sort = {
diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts
index db8a3f25bd..6645751871 100644
--- a/src/api/endpoints/i/update.ts
+++ b/src/api/endpoints/i/update.ts
@@ -36,20 +36,20 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 	if (birthdayErr) return rej('invalid birthday param');
 	if (birthday !== undefined) user.account.profile.birthday = birthday;
 
-	// Get 'avatar_id' parameter
-	const [avatarId, avatarIdErr] = $(params.avatar_id).optional.id().$;
-	if (avatarIdErr) return rej('invalid avatar_id param');
-	if (avatarId) user.avatar_id = avatarId;
+	// Get 'avatarId' parameter
+	const [avatarId, avatarIdErr] = $(params.avatarId).optional.id().$;
+	if (avatarIdErr) return rej('invalid avatarId param');
+	if (avatarId) user.avatarId = avatarId;
 
-	// Get 'banner_id' parameter
-	const [bannerId, bannerIdErr] = $(params.banner_id).optional.id().$;
-	if (bannerIdErr) return rej('invalid banner_id param');
-	if (bannerId) user.banner_id = bannerId;
+	// Get 'bannerId' parameter
+	const [bannerId, bannerIdErr] = $(params.bannerId).optional.id().$;
+	if (bannerIdErr) return rej('invalid bannerId param');
+	if (bannerId) user.bannerId = bannerId;
 
-	// Get 'is_bot' parameter
-	const [isBot, isBotErr] = $(params.is_bot).optional.boolean().$;
-	if (isBotErr) return rej('invalid is_bot param');
-	if (isBot != null) user.account.is_bot = isBot;
+	// Get 'isBot' parameter
+	const [isBot, isBotErr] = $(params.isBot).optional.boolean().$;
+	if (isBotErr) return rej('invalid isBot param');
+	if (isBot != null) user.account.isBot = isBot;
 
 	// Get 'auto_watch' parameter
 	const [autoWatch, autoWatchErr] = $(params.auto_watch).optional.boolean().$;
@@ -60,10 +60,10 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 		$set: {
 			name: user.name,
 			description: user.description,
-			avatar_id: user.avatar_id,
-			banner_id: user.banner_id,
+			avatarId: user.avatarId,
+			bannerId: user.bannerId,
 			'account.profile': user.account.profile,
-			'account.is_bot': user.account.is_bot,
+			'account.isBot': user.account.isBot,
 			'account.settings': user.account.settings
 		}
 	});
diff --git a/src/api/endpoints/i/update_client_setting.ts b/src/api/endpoints/i/update_client_setting.ts
index c772ed5dc3..a0bef5e595 100644
--- a/src/api/endpoints/i/update_client_setting.ts
+++ b/src/api/endpoints/i/update_client_setting.ts
@@ -22,14 +22,14 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (valueErr) return rej('invalid value param');
 
 	const x = {};
-	x[`account.client_settings.${name}`] = value;
+	x[`account.clientSettings.${name}`] = value;
 
 	await User.update(user._id, {
 		$set: x
 	});
 
 	// Serialize
-	user.account.client_settings[name] = value;
+	user.account.clientSettings[name] = value;
 	const iObj = await pack(user, user, {
 		detail: true,
 		includeSecrets: true
diff --git a/src/api/endpoints/i/update_home.ts b/src/api/endpoints/i/update_home.ts
index 9ce44e25ee..151c3e205f 100644
--- a/src/api/endpoints/i/update_home.ts
+++ b/src/api/endpoints/i/update_home.ts
@@ -26,7 +26,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (home) {
 		await User.update(user._id, {
 			$set: {
-				'account.client_settings.home': home
+				'account.clientSettings.home': home
 			}
 		});
 
@@ -38,7 +38,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	} else {
 		if (id == null && data == null) return rej('you need to set id and data params if home param unset');
 
-		const _home = user.account.client_settings.home;
+		const _home = user.account.clientSettings.home;
 		const widget = _home.find(w => w.id == id);
 
 		if (widget == null) return rej('widget not found');
@@ -47,7 +47,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 		await User.update(user._id, {
 			$set: {
-				'account.client_settings.home': _home
+				'account.clientSettings.home': _home
 			}
 		});
 
diff --git a/src/api/endpoints/i/update_mobile_home.ts b/src/api/endpoints/i/update_mobile_home.ts
index 1daddf42b9..a8436b940f 100644
--- a/src/api/endpoints/i/update_mobile_home.ts
+++ b/src/api/endpoints/i/update_mobile_home.ts
@@ -25,7 +25,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (home) {
 		await User.update(user._id, {
 			$set: {
-				'account.client_settings.mobile_home': home
+				'account.clientSettings.mobile_home': home
 			}
 		});
 
@@ -37,7 +37,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	} else {
 		if (id == null && data == null) return rej('you need to set id and data params if home param unset');
 
-		const _home = user.account.client_settings.mobile_home || [];
+		const _home = user.account.clientSettings.mobile_home || [];
 		const widget = _home.find(w => w.id == id);
 
 		if (widget == null) return rej('widget not found');
@@ -46,7 +46,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 		await User.update(user._id, {
 			$set: {
-				'account.client_settings.mobile_home': _home
+				'account.clientSettings.mobile_home': _home
 			}
 		});
 
diff --git a/src/api/endpoints/messaging/history.ts b/src/api/endpoints/messaging/history.ts
index 1683ca7a89..2bf3ed996d 100644
--- a/src/api/endpoints/messaging/history.ts
+++ b/src/api/endpoints/messaging/history.ts
@@ -19,25 +19,25 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (limitErr) return rej('invalid limit param');
 
 	const mute = await Mute.find({
-		muter_id: user._id,
-		deleted_at: { $exists: false }
+		muterId: user._id,
+		deletedAt: { $exists: false }
 	});
 
 	// Get history
 	const history = await History
 		.find({
-			user_id: user._id,
-			partner: {
-				$nin: mute.map(m => m.mutee_id)
+			userId: user._id,
+			partnerId: {
+				$nin: mute.map(m => m.muteeId)
 			}
 		}, {
 			limit: limit,
 			sort: {
-				updated_at: -1
+				updatedAt: -1
 			}
 		});
 
 	// Serialize
 	res(await Promise.all(history.map(async h =>
-		await pack(h.message, user))));
+		await pack(h.messageId, user))));
 });
diff --git a/src/api/endpoints/messaging/messages.ts b/src/api/endpoints/messaging/messages.ts
index 67ba5e9d6d..ba8ca7d1c2 100644
--- a/src/api/endpoints/messaging/messages.ts
+++ b/src/api/endpoints/messaging/messages.ts
@@ -15,9 +15,9 @@ import read from '../../common/read-messaging-message';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [recipientId, recipientIdErr] = $(params.user_id).id().$;
-	if (recipientIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [recipientId, recipientIdErr] = $(params.userId).id().$;
+	if (recipientIdErr) return rej('invalid userId param');
 
 	// Fetch recipient
 	const recipient = await User.findOne({
@@ -55,11 +55,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	const query = {
 		$or: [{
-			user_id: user._id,
-			recipient_id: recipient._id
+			userId: user._id,
+			recipientId: recipient._id
 		}, {
-			user_id: recipient._id,
-			recipient_id: user._id
+			userId: recipient._id,
+			recipientId: user._id
 		}]
 	} as any;
 
diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts
index 1b8a5f59e6..b94a90678e 100644
--- a/src/api/endpoints/messaging/messages/create.ts
+++ b/src/api/endpoints/messaging/messages/create.ts
@@ -21,9 +21,9 @@ import config from '../../../../conf';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [recipientId, recipientIdErr] = $(params.user_id).id().$;
-	if (recipientIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [recipientId, recipientIdErr] = $(params.userId).id().$;
+	if (recipientIdErr) return rej('invalid userId param');
 
 	// Myself
 	if (recipientId.equals(user._id)) {
@@ -47,15 +47,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$;
 	if (textErr) return rej('invalid text');
 
-	// Get 'file_id' parameter
-	const [fileId, fileIdErr] = $(params.file_id).optional.id().$;
-	if (fileIdErr) return rej('invalid file_id param');
+	// Get 'fileId' parameter
+	const [fileId, fileIdErr] = $(params.fileId).optional.id().$;
+	if (fileIdErr) return rej('invalid fileId param');
 
 	let file = null;
 	if (fileId !== undefined) {
 		file = await DriveFile.findOne({
 			_id: fileId,
-			'metadata.user_id': user._id
+			'metadata.userId': user._id
 		});
 
 		if (file === null) {
@@ -70,12 +70,12 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// メッセージを作成
 	const message = await Message.insert({
-		created_at: new Date(),
-		file_id: file ? file._id : undefined,
-		recipient_id: recipient._id,
+		createdAt: new Date(),
+		fileId: file ? file._id : undefined,
+		recipientId: recipient._id,
 		text: text ? text : undefined,
-		user_id: user._id,
-		is_read: false
+		userId: user._id,
+		isRead: false
 	});
 
 	// Serialize
@@ -85,32 +85,32 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	res(messageObj);
 
 	// 自分のストリーム
-	publishMessagingStream(message.user_id, message.recipient_id, 'message', messageObj);
-	publishMessagingIndexStream(message.user_id, 'message', messageObj);
-	publishUserStream(message.user_id, 'messaging_message', messageObj);
+	publishMessagingStream(message.userId, message.recipientId, 'message', messageObj);
+	publishMessagingIndexStream(message.userId, 'message', messageObj);
+	publishUserStream(message.userId, 'messaging_message', messageObj);
 
 	// 相手のストリーム
-	publishMessagingStream(message.recipient_id, message.user_id, 'message', messageObj);
-	publishMessagingIndexStream(message.recipient_id, 'message', messageObj);
-	publishUserStream(message.recipient_id, 'messaging_message', messageObj);
+	publishMessagingStream(message.recipientId, message.userId, 'message', messageObj);
+	publishMessagingIndexStream(message.recipientId, 'message', messageObj);
+	publishUserStream(message.recipientId, 'messaging_message', messageObj);
 
 	// 3秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
 	setTimeout(async () => {
-		const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true });
-		if (!freshMessage.is_read) {
+		const freshMessage = await Message.findOne({ _id: message._id }, { isRead: true });
+		if (!freshMessage.isRead) {
 			//#region ただしミュートされているなら発行しない
 			const mute = await Mute.find({
-				muter_id: recipient._id,
-				deleted_at: { $exists: false }
+				muterId: recipient._id,
+				deletedAt: { $exists: false }
 			});
-			const mutedUserIds = mute.map(m => m.mutee_id.toString());
+			const mutedUserIds = mute.map(m => m.muteeId.toString());
 			if (mutedUserIds.indexOf(user._id.toString()) != -1) {
 				return;
 			}
 			//#endregion
 
-			publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj);
-			pushSw(message.recipient_id, 'unread_messaging_message', messageObj);
+			publishUserStream(message.recipientId, 'unread_messaging_message', messageObj);
+			pushSw(message.recipientId, 'unread_messaging_message', messageObj);
 		}
 	}, 3000);
 
@@ -130,26 +130,26 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// 履歴作成(自分)
 	History.update({
-		user_id: user._id,
-		partner: recipient._id
+		userId: user._id,
+		partnerId: recipient._id
 	}, {
-		updated_at: new Date(),
-		user_id: user._id,
-		partner: recipient._id,
-		message: message._id
+		updatedAt: new Date(),
+		userId: user._id,
+		partnerId: recipient._id,
+		messageId: message._id
 	}, {
 		upsert: true
 	});
 
 	// 履歴作成(相手)
 	History.update({
-		user_id: recipient._id,
-		partner: user._id
+		userId: recipient._id,
+		partnerId: user._id
 	}, {
-		updated_at: new Date(),
-		user_id: recipient._id,
-		partner: user._id,
-		message: message._id
+		updatedAt: new Date(),
+		userId: recipient._id,
+		partnerId: user._id,
+		messageId: message._id
 	}, {
 		upsert: true
 	});
diff --git a/src/api/endpoints/messaging/unread.ts b/src/api/endpoints/messaging/unread.ts
index c4326e1d22..f7f4047b67 100644
--- a/src/api/endpoints/messaging/unread.ts
+++ b/src/api/endpoints/messaging/unread.ts
@@ -13,18 +13,18 @@ import Mute from '../../models/mute';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const mute = await Mute.find({
-		muter_id: user._id,
-		deleted_at: { $exists: false }
+		muterId: user._id,
+		deletedAt: { $exists: false }
 	});
-	const mutedUserIds = mute.map(m => m.mutee_id);
+	const mutedUserIds = mute.map(m => m.muteeId);
 
 	const count = await Message
 		.count({
-			user_id: {
+			userId: {
 				$nin: mutedUserIds
 			},
-			recipient_id: user._id,
-			is_read: false
+			recipientId: user._id,
+			isRead: false
 		});
 
 	res({
diff --git a/src/api/endpoints/mute/create.ts b/src/api/endpoints/mute/create.ts
index f99b40d32e..e860235086 100644
--- a/src/api/endpoints/mute/create.ts
+++ b/src/api/endpoints/mute/create.ts
@@ -15,9 +15,9 @@ import Mute from '../../models/mute';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const muter = user;
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// 自分自身
 	if (user._id.equals(userId)) {
@@ -40,9 +40,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Check if already muting
 	const exist = await Mute.findOne({
-		muter_id: muter._id,
-		mutee_id: mutee._id,
-		deleted_at: { $exists: false }
+		muterId: muter._id,
+		muteeId: mutee._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -51,9 +51,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create mute
 	await Mute.insert({
-		created_at: new Date(),
-		muter_id: muter._id,
-		mutee_id: mutee._id,
+		createdAt: new Date(),
+		muterId: muter._id,
+		muteeId: mutee._id,
 	});
 
 	// Send response
diff --git a/src/api/endpoints/mute/delete.ts b/src/api/endpoints/mute/delete.ts
index 36e2fd101a..7e361b4792 100644
--- a/src/api/endpoints/mute/delete.ts
+++ b/src/api/endpoints/mute/delete.ts
@@ -15,9 +15,9 @@ import Mute from '../../models/mute';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const muter = user;
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Check if the mutee is yourself
 	if (user._id.equals(userId)) {
@@ -40,9 +40,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Check not muting
 	const exist = await Mute.findOne({
-		muter_id: muter._id,
-		mutee_id: mutee._id,
-		deleted_at: { $exists: false }
+		muterId: muter._id,
+		muteeId: mutee._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist === null) {
@@ -54,7 +54,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: exist._id
 	}, {
 		$set: {
-			deleted_at: new Date()
+			deletedAt: new Date()
 		}
 	});
 
diff --git a/src/api/endpoints/mute/list.ts b/src/api/endpoints/mute/list.ts
index 19e3b157e6..3401fba64d 100644
--- a/src/api/endpoints/mute/list.ts
+++ b/src/api/endpoints/mute/list.ts
@@ -28,15 +28,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Construct query
 	const query = {
-		muter_id: me._id,
-		deleted_at: { $exists: false }
+		muterId: me._id,
+		deletedAt: { $exists: false }
 	} as any;
 
 	if (iknow) {
 		// Get my friends
 		const myFriends = await getFriends(me._id);
 
-		query.mutee_id = {
+		query.muteeId = {
 			$in: myFriends
 		};
 	}
@@ -63,7 +63,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Serialize
 	const users = await Promise.all(mutes.map(async m =>
-		await pack(m.mutee_id, me, { detail: true })));
+		await pack(m.muteeId, me, { detail: true })));
 
 	// Response
 	res({
diff --git a/src/api/endpoints/my/apps.ts b/src/api/endpoints/my/apps.ts
index b236190506..bc1290cac6 100644
--- a/src/api/endpoints/my/apps.ts
+++ b/src/api/endpoints/my/apps.ts
@@ -21,7 +21,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (offsetErr) return rej('invalid offset param');
 
 	const query = {
-		user_id: user._id
+		userId: user._id
 	};
 
 	// Execute query
diff --git a/src/api/endpoints/notifications/get_unread_count.ts b/src/api/endpoints/notifications/get_unread_count.ts
index 845d6b29ce..8f9719fff6 100644
--- a/src/api/endpoints/notifications/get_unread_count.ts
+++ b/src/api/endpoints/notifications/get_unread_count.ts
@@ -13,18 +13,18 @@ import Mute from '../../models/mute';
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	const mute = await Mute.find({
-		muter_id: user._id,
-		deleted_at: { $exists: false }
+		muterId: user._id,
+		deletedAt: { $exists: false }
 	});
-	const mutedUserIds = mute.map(m => m.mutee_id);
+	const mutedUserIds = mute.map(m => m.muteeId);
 
 	const count = await Notification
 		.count({
-			notifiee_id: user._id,
-			notifier_id: {
+			notifieeId: user._id,
+			notifierId: {
 				$nin: mutedUserIds
 			},
-			is_read: false
+			isRead: false
 		});
 
 	res({
diff --git a/src/api/endpoints/notifications/mark_as_read_all.ts b/src/api/endpoints/notifications/mark_as_read_all.ts
index 3550e344c4..693de3d0ef 100644
--- a/src/api/endpoints/notifications/mark_as_read_all.ts
+++ b/src/api/endpoints/notifications/mark_as_read_all.ts
@@ -14,11 +14,11 @@ import event from '../../event';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Update documents
 	await Notification.update({
-		notifiee_id: user._id,
-		is_read: false
+		notifieeId: user._id,
+		isRead: false
 	}, {
 		$set: {
-			is_read: true
+			isRead: true
 		}
 	}, {
 		multi: true
diff --git a/src/api/endpoints/othello/games.ts b/src/api/endpoints/othello/games.ts
index f6e38b8d87..5c71f98828 100644
--- a/src/api/endpoints/othello/games.ts
+++ b/src/api/endpoints/othello/games.ts
@@ -24,14 +24,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	const q: any = my ? {
-		is_started: true,
+		isStarted: true,
 		$or: [{
-			user1_id: user._id
+			user1Id: user._id
 		}, {
-			user2_id: user._id
+			user2Id: user._id
 		}]
 	} : {
-		is_started: true
+		isStarted: true
 	};
 
 	const sort = {
diff --git a/src/api/endpoints/othello/games/show.ts b/src/api/endpoints/othello/games/show.ts
index c7bd74a39a..19f5d0fef0 100644
--- a/src/api/endpoints/othello/games/show.ts
+++ b/src/api/endpoints/othello/games/show.ts
@@ -14,9 +14,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	const o = new Othello(game.settings.map, {
-		isLlotheo: game.settings.is_llotheo,
-		canPutEverywhere: game.settings.can_put_everywhere,
-		loopedBoard: game.settings.looped_board
+		isLlotheo: game.settings.isLlotheo,
+		canPutEverywhere: game.settings.canPutEverywhere,
+		loopedBoard: game.settings.loopedBoard
 	});
 
 	game.logs.forEach(log => {
diff --git a/src/api/endpoints/othello/invitations.ts b/src/api/endpoints/othello/invitations.ts
index 02fb421fbc..f6e0071a6c 100644
--- a/src/api/endpoints/othello/invitations.ts
+++ b/src/api/endpoints/othello/invitations.ts
@@ -3,7 +3,7 @@ import Matching, { pack as packMatching } from '../../models/othello-matching';
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Find session
 	const invitations = await Matching.find({
-		child_id: user._id
+		childId: user._id
 	}, {
 		sort: {
 			_id: -1
diff --git a/src/api/endpoints/othello/match.ts b/src/api/endpoints/othello/match.ts
index f73386ba7c..f503c5834c 100644
--- a/src/api/endpoints/othello/match.ts
+++ b/src/api/endpoints/othello/match.ts
@@ -6,19 +6,19 @@ import publishUserStream, { publishOthelloStream } from '../../event';
 import { eighteight } from '../../../common/othello/maps';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [childId, childIdErr] = $(params.user_id).id().$;
-	if (childIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [childId, childIdErr] = $(params.userId).id().$;
+	if (childIdErr) return rej('invalid userId param');
 
 	// Myself
 	if (childId.equals(user._id)) {
-		return rej('invalid user_id param');
+		return rej('invalid userId param');
 	}
 
 	// Find session
 	const exist = await Matching.findOne({
-		parent_id: childId,
-		child_id: user._id
+		parentId: childId,
+		childId: user._id
 	});
 
 	if (exist) {
@@ -29,28 +29,28 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 		// Create game
 		const game = await OthelloGame.insert({
-			created_at: new Date(),
-			user1_id: exist.parent_id,
-			user2_id: user._id,
-			user1_accepted: false,
-			user2_accepted: false,
-			is_started: false,
-			is_ended: false,
+			createdAt: new Date(),
+			user1Id: exist.parentId,
+			user2Id: user._id,
+			user1Accepted: false,
+			user2Accepted: false,
+			isStarted: false,
+			isEnded: false,
 			logs: [],
 			settings: {
 				map: eighteight.data,
 				bw: 'random',
-				is_llotheo: false
+				isLlotheo: false
 			}
 		});
 
 		// Reponse
 		res(await packGame(game, user));
 
-		publishOthelloStream(exist.parent_id, 'matched', await packGame(game, exist.parent_id));
+		publishOthelloStream(exist.parentId, 'matched', await packGame(game, exist.parentId));
 
 		const other = await Matching.count({
-			child_id: user._id
+			childId: user._id
 		});
 
 		if (other == 0) {
@@ -72,14 +72,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 		// 以前のセッションはすべて削除しておく
 		await Matching.remove({
-			parent_id: user._id
+			parentId: user._id
 		});
 
 		// セッションを作成
 		const matching = await Matching.insert({
-			created_at: new Date(),
-			parent_id: user._id,
-			child_id: child._id
+			createdAt: new Date(),
+			parentId: user._id,
+			childId: child._id
 		});
 
 		// Reponse
diff --git a/src/api/endpoints/othello/match/cancel.ts b/src/api/endpoints/othello/match/cancel.ts
index 6f751ef835..ee0f82a611 100644
--- a/src/api/endpoints/othello/match/cancel.ts
+++ b/src/api/endpoints/othello/match/cancel.ts
@@ -2,7 +2,7 @@ import Matching from '../../../models/othello-matching';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
 	await Matching.remove({
-		parent_id: user._id
+		parentId: user._id
 	});
 
 	res();
diff --git a/src/api/endpoints/posts.ts b/src/api/endpoints/posts.ts
index 7df744d2a3..7e9ff3ad74 100644
--- a/src/api/endpoints/posts.ts
+++ b/src/api/endpoints/posts.ts
@@ -65,15 +65,15 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	}
 
 	if (reply != undefined) {
-		query.reply_id = reply ? { $exists: true, $ne: null } : null;
+		query.replyId = reply ? { $exists: true, $ne: null } : null;
 	}
 
 	if (repost != undefined) {
-		query.repost_id = repost ? { $exists: true, $ne: null } : null;
+		query.repostId = repost ? { $exists: true, $ne: null } : null;
 	}
 
 	if (media != undefined) {
-		query.media_ids = media ? { $exists: true, $ne: null } : null;
+		query.mediaIds = media ? { $exists: true, $ne: null } : null;
 	}
 
 	if (poll != undefined) {
@@ -82,7 +82,7 @@ module.exports = (params) => new Promise(async (res, rej) => {
 
 	// TODO
 	//if (bot != undefined) {
-	//	query.is_bot = bot;
+	//	query.isBot = bot;
 	//}
 
 	// Issue query
diff --git a/src/api/endpoints/posts/categorize.ts b/src/api/endpoints/posts/categorize.ts
index 0c85c2b4e0..0436c8e697 100644
--- a/src/api/endpoints/posts/categorize.ts
+++ b/src/api/endpoints/posts/categorize.ts
@@ -12,13 +12,13 @@ import Post from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	if (!user.account.is_pro) {
+	if (!user.account.isPro) {
 		return rej('This endpoint is available only from a Pro account');
 	}
 
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get categorizee
 	const post = await Post.findOne({
diff --git a/src/api/endpoints/posts/context.ts b/src/api/endpoints/posts/context.ts
index 5ba3758975..44a77d102e 100644
--- a/src/api/endpoints/posts/context.ts
+++ b/src/api/endpoints/posts/context.ts
@@ -12,9 +12,9 @@ import Post, { pack } from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
@@ -48,13 +48,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 			return;
 		}
 
-		if (p.reply_id) {
-			await get(p.reply_id);
+		if (p.replyId) {
+			await get(p.replyId);
 		}
 	}
 
-	if (post.reply_id) {
-		await get(post.reply_id);
+	if (post.replyId) {
+		await get(post.replyId);
 	}
 
 	// Serialize
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 286e18bb76..2a3d974fe8 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -33,9 +33,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 	const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$;
 	if (textErr) return rej('invalid text');
 
-	// Get 'via_mobile' parameter
-	const [viaMobile = false, viaMobileErr] = $(params.via_mobile).optional.boolean().$;
-	if (viaMobileErr) return rej('invalid via_mobile');
+	// Get 'viaMobile' parameter
+	const [viaMobile = false, viaMobileErr] = $(params.viaMobile).optional.boolean().$;
+	if (viaMobileErr) return rej('invalid viaMobile');
 
 	// Get 'tags' parameter
 	const [tags = [], tagsErr] = $(params.tags).optional.array('string').unique().eachQ(t => t.range(1, 32)).$;
@@ -53,9 +53,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		.$;
 	if (geoErr) return rej('invalid geo');
 
-	// Get 'media_ids' parameter
-	const [mediaIds, mediaIdsErr] = $(params.media_ids).optional.array('id').unique().range(1, 4).$;
-	if (mediaIdsErr) return rej('invalid media_ids');
+	// Get 'mediaIds' parameter
+	const [mediaIds, mediaIdsErr] = $(params.mediaIds).optional.array('id').unique().range(1, 4).$;
+	if (mediaIdsErr) return rej('invalid mediaIds');
 
 	let files = [];
 	if (mediaIds !== undefined) {
@@ -67,7 +67,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 			// SELECT _id
 			const entity = await DriveFile.findOne({
 				_id: mediaId,
-				'metadata.user_id': user._id
+				'metadata.userId': user._id
 			});
 
 			if (entity === null) {
@@ -80,9 +80,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		files = null;
 	}
 
-	// Get 'repost_id' parameter
-	const [repostId, repostIdErr] = $(params.repost_id).optional.id().$;
-	if (repostIdErr) return rej('invalid repost_id');
+	// Get 'repostId' parameter
+	const [repostId, repostIdErr] = $(params.repostId).optional.id().$;
+	if (repostIdErr) return rej('invalid repostId');
 
 	let repost: IPost = null;
 	let isQuote = false;
@@ -94,13 +94,13 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 		if (repost == null) {
 			return rej('repostee is not found');
-		} else if (repost.repost_id && !repost.text && !repost.media_ids) {
+		} else if (repost.repostId && !repost.text && !repost.mediaIds) {
 			return rej('cannot repost to repost');
 		}
 
 		// Fetch recently post
 		const latestPost = await Post.findOne({
-			user_id: user._id
+			userId: user._id
 		}, {
 			sort: {
 				_id: -1
@@ -111,8 +111,8 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 		// 直近と同じRepost対象かつ引用じゃなかったらエラー
 		if (latestPost &&
-			latestPost.repost_id &&
-			latestPost.repost_id.equals(repost._id) &&
+			latestPost.repostId &&
+			latestPost.repostId.equals(repost._id) &&
 			!isQuote) {
 			return rej('cannot repost same post that already reposted in your latest post');
 		}
@@ -125,9 +125,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		}
 	}
 
-	// Get 'reply_id' parameter
-	const [replyId, replyIdErr] = $(params.reply_id).optional.id().$;
-	if (replyIdErr) return rej('invalid reply_id');
+	// Get 'replyId' parameter
+	const [replyId, replyIdErr] = $(params.replyId).optional.id().$;
+	if (replyIdErr) return rej('invalid replyId');
 
 	let reply: IPost = null;
 	if (replyId !== undefined) {
@@ -141,14 +141,14 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		}
 
 		// 返信対象が引用でないRepostだったらエラー
-		if (reply.repost_id && !reply.text && !reply.media_ids) {
+		if (reply.repostId && !reply.text && !reply.mediaIds) {
 			return rej('cannot reply to repost');
 		}
 	}
 
-	// Get 'channel_id' parameter
-	const [channelId, channelIdErr] = $(params.channel_id).optional.id().$;
-	if (channelIdErr) return rej('invalid channel_id');
+	// Get 'channelId' parameter
+	const [channelId, channelIdErr] = $(params.channelId).optional.id().$;
+	if (channelIdErr) return rej('invalid channelId');
 
 	let channel: IChannel = null;
 	if (channelId !== undefined) {
@@ -162,12 +162,12 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		}
 
 		// 返信対象の投稿がこのチャンネルじゃなかったらダメ
-		if (reply && !channelId.equals(reply.channel_id)) {
+		if (reply && !channelId.equals(reply.channelId)) {
 			return rej('チャンネル内部からチャンネル外部の投稿に返信することはできません');
 		}
 
 		// Repost対象の投稿がこのチャンネルじゃなかったらダメ
-		if (repost && !channelId.equals(repost.channel_id)) {
+		if (repost && !channelId.equals(repost.channelId)) {
 			return rej('チャンネル内部からチャンネル外部の投稿をRepostすることはできません');
 		}
 
@@ -177,12 +177,12 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		}
 	} else {
 		// 返信対象の投稿がチャンネルへの投稿だったらダメ
-		if (reply && reply.channel_id != null) {
+		if (reply && reply.channelId != null) {
 			return rej('チャンネル外部からチャンネル内部の投稿に返信することはできません');
 		}
 
 		// Repost対象の投稿がチャンネルへの投稿だったらダメ
-		if (repost && repost.channel_id != null) {
+		if (repost && repost.channelId != null) {
 			return rej('チャンネル外部からチャンネル内部の投稿をRepostすることはできません');
 		}
 	}
@@ -206,7 +206,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 	// テキストが無いかつ添付ファイルが無いかつRepostも無いかつ投票も無かったらエラー
 	if (text === undefined && files === null && repost === null && poll === undefined) {
-		return rej('text, media_ids, repost_id or poll is required');
+		return rej('text, mediaIds, repostId or poll is required');
 	}
 
 	// 直近の投稿と重複してたらエラー
@@ -214,14 +214,14 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 	if (user.latest_post) {
 		if (deepEqual({
 			text: user.latest_post.text,
-			reply: user.latest_post.reply_id ? user.latest_post.reply_id.toString() : null,
-			repost: user.latest_post.repost_id ? user.latest_post.repost_id.toString() : null,
-			media_ids: (user.latest_post.media_ids || []).map(id => id.toString())
+			reply: user.latest_post.replyId ? user.latest_post.replyId.toString() : null,
+			repost: user.latest_post.repostId ? user.latest_post.repostId.toString() : null,
+			mediaIds: (user.latest_post.mediaIds || []).map(id => id.toString())
 		}, {
 			text: text,
 			reply: reply ? reply._id.toString() : null,
 			repost: repost ? repost._id.toString() : null,
-			media_ids: (files || []).map(file => file._id.toString())
+			mediaIds: (files || []).map(file => file._id.toString())
 		})) {
 			return rej('duplicate');
 		}
@@ -246,23 +246,23 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 	// 投稿を作成
 	const post = await Post.insert({
-		created_at: new Date(),
-		channel_id: channel ? channel._id : undefined,
+		createdAt: new Date(),
+		channelId: channel ? channel._id : undefined,
 		index: channel ? channel.index + 1 : undefined,
-		media_ids: files ? files.map(file => file._id) : undefined,
-		reply_id: reply ? reply._id : undefined,
-		repost_id: repost ? repost._id : undefined,
+		mediaIds: files ? files.map(file => file._id) : undefined,
+		replyId: reply ? reply._id : undefined,
+		repostId: repost ? repost._id : undefined,
 		poll: poll,
 		text: text,
 		tags: tags,
-		user_id: user._id,
-		app_id: app ? app._id : null,
-		via_mobile: viaMobile,
+		userId: user._id,
+		appId: app ? app._id : null,
+		viaMobile: viaMobile,
 		geo,
 
 		// 以下非正規化データ
-		_reply: reply ? { user_id: reply.user_id } : undefined,
-		_repost: repost ? { user_id: repost.user_id } : undefined,
+		_reply: reply ? { userId: reply.userId } : undefined,
+		_repost: repost ? { userId: repost.userId } : undefined,
 	});
 
 	// Serialize
@@ -293,10 +293,10 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		// Publish event
 		if (!user._id.equals(mentionee)) {
 			const mentioneeMutes = await Mute.find({
-				muter_id: mentionee,
-				deleted_at: { $exists: false }
+				muterId: mentionee,
+				deletedAt: { $exists: false }
 			});
-			const mentioneesMutedUserIds = mentioneeMutes.map(m => m.mutee_id.toString());
+			const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString());
 			if (mentioneesMutedUserIds.indexOf(user._id.toString()) == -1) {
 				event(mentionee, reason, postObj);
 				pushSw(mentionee, reason, postObj);
@@ -312,17 +312,17 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		// Fetch all followers
 		const followers = await Following
 			.find({
-				followee_id: user._id,
+				followeeId: user._id,
 				// 削除されたドキュメントは除く
-				deleted_at: { $exists: false }
+				deletedAt: { $exists: false }
 			}, {
-				follower_id: true,
+				followerId: true,
 				_id: false
 			});
 
 		// Publish event to followers stream
 		followers.forEach(following =>
-			event(following.follower_id, 'post', postObj));
+			event(following.followerId, 'post', postObj));
 	}
 
 	// チャンネルへの投稿
@@ -339,21 +339,21 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 		// Get channel watchers
 		const watches = await ChannelWatching.find({
-			channel_id: channel._id,
+			channelId: channel._id,
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
+			deletedAt: { $exists: false }
 		});
 
 		// チャンネルの視聴者(のタイムライン)に配信
 		watches.forEach(w => {
-			event(w.user_id, 'post', postObj);
+			event(w.userId, 'post', postObj);
 		});
 	}
 
 	// Increment my posts count
 	User.update({ _id: user._id }, {
 		$inc: {
-			posts_count: 1
+			postsCount: 1
 		}
 	});
 
@@ -367,26 +367,26 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		});
 
 		// 自分自身へのリプライでない限りは通知を作成
-		notify(reply.user_id, user._id, 'reply', {
-			post_id: post._id
+		notify(reply.userId, user._id, 'reply', {
+			postId: post._id
 		});
 
 		// Fetch watchers
 		Watching
 			.find({
-				post_id: reply._id,
-				user_id: { $ne: user._id },
+				postId: reply._id,
+				userId: { $ne: user._id },
 				// 削除されたドキュメントは除く
-				deleted_at: { $exists: false }
+				deletedAt: { $exists: false }
 			}, {
 				fields: {
-					user_id: true
+					userId: true
 				}
 			})
 			.then(watchers => {
 				watchers.forEach(watcher => {
-					notify(watcher.user_id, user._id, 'reply', {
-						post_id: post._id
+					notify(watcher.userId, user._id, 'reply', {
+						postId: post._id
 					});
 				});
 			});
@@ -397,33 +397,33 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		}
 
 		// Add mention
-		addMention(reply.user_id, 'reply');
+		addMention(reply.userId, 'reply');
 	}
 
 	// If it is repost
 	if (repost) {
 		// Notify
 		const type = text ? 'quote' : 'repost';
-		notify(repost.user_id, user._id, type, {
-			post_id: post._id
+		notify(repost.userId, user._id, type, {
+			postId: post._id
 		});
 
 		// Fetch watchers
 		Watching
 			.find({
-				post_id: repost._id,
-				user_id: { $ne: user._id },
+				postId: repost._id,
+				userId: { $ne: user._id },
 				// 削除されたドキュメントは除く
-				deleted_at: { $exists: false }
+				deletedAt: { $exists: false }
 			}, {
 				fields: {
-					user_id: true
+					userId: true
 				}
 			})
 			.then(watchers => {
 				watchers.forEach(watcher => {
-					notify(watcher.user_id, user._id, type, {
-						post_id: post._id
+					notify(watcher.userId, user._id, type, {
+						postId: post._id
 					});
 				});
 			});
@@ -436,18 +436,18 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		// If it is quote repost
 		if (text) {
 			// Add mention
-			addMention(repost.user_id, 'quote');
+			addMention(repost.userId, 'quote');
 		} else {
 			// Publish event
-			if (!user._id.equals(repost.user_id)) {
-				event(repost.user_id, 'repost', postObj);
+			if (!user._id.equals(repost.userId)) {
+				event(repost.userId, 'repost', postObj);
 			}
 		}
 
 		// 今までで同じ投稿をRepostしているか
 		const existRepost = await Post.findOne({
-			user_id: user._id,
-			repost_id: repost._id,
+			userId: user._id,
+			repostId: repost._id,
 			_id: {
 				$ne: post._id
 			}
@@ -494,15 +494,15 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 			if (mentionee == null) return;
 
 			// 既に言及されたユーザーに対する返信や引用repostの場合も無視
-			if (reply && reply.user_id.equals(mentionee._id)) return;
-			if (repost && repost.user_id.equals(mentionee._id)) return;
+			if (reply && reply.userId.equals(mentionee._id)) return;
+			if (repost && repost.userId.equals(mentionee._id)) return;
 
 			// Add mention
 			addMention(mentionee._id, 'mention');
 
 			// Create notification
 			notify(mentionee._id, user._id, 'mention', {
-				post_id: post._id
+				postId: post._id
 			});
 
 			return;
diff --git a/src/api/endpoints/posts/favorites/create.ts b/src/api/endpoints/posts/favorites/create.ts
index f9dee271b5..6100e10b23 100644
--- a/src/api/endpoints/posts/favorites/create.ts
+++ b/src/api/endpoints/posts/favorites/create.ts
@@ -13,9 +13,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get favoritee
 	const post = await Post.findOne({
@@ -28,8 +28,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// if already favorited
 	const exist = await Favorite.findOne({
-		post_id: post._id,
-		user_id: user._id
+		postId: post._id,
+		userId: user._id
 	});
 
 	if (exist !== null) {
@@ -38,9 +38,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create favorite
 	await Favorite.insert({
-		created_at: new Date(),
-		post_id: post._id,
-		user_id: user._id
+		createdAt: new Date(),
+		postId: post._id,
+		userId: user._id
 	});
 
 	// Send response
diff --git a/src/api/endpoints/posts/favorites/delete.ts b/src/api/endpoints/posts/favorites/delete.ts
index c4fe7d3234..b1b4fcebc4 100644
--- a/src/api/endpoints/posts/favorites/delete.ts
+++ b/src/api/endpoints/posts/favorites/delete.ts
@@ -13,9 +13,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get favoritee
 	const post = await Post.findOne({
@@ -28,8 +28,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// if already favorited
 	const exist = await Favorite.findOne({
-		post_id: post._id,
-		user_id: user._id
+		postId: post._id,
+		userId: user._id
 	});
 
 	if (exist === null) {
diff --git a/src/api/endpoints/posts/mentions.ts b/src/api/endpoints/posts/mentions.ts
index 7127db0ad1..da90583bbd 100644
--- a/src/api/endpoints/posts/mentions.ts
+++ b/src/api/endpoints/posts/mentions.ts
@@ -48,7 +48,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (following) {
 		const followingIds = await getFriends(user._id);
 
-		query.user_id = {
+		query.userId = {
 			$in: followingIds
 		};
 	}
diff --git a/src/api/endpoints/posts/polls/recommendation.ts b/src/api/endpoints/posts/polls/recommendation.ts
index 4a3fa3f55e..19ef0975fa 100644
--- a/src/api/endpoints/posts/polls/recommendation.ts
+++ b/src/api/endpoints/posts/polls/recommendation.ts
@@ -23,22 +23,22 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Get votes
 	const votes = await Vote.find({
-		user_id: user._id
+		userId: user._id
 	}, {
 		fields: {
 			_id: false,
-			post_id: true
+			postId: true
 		}
 	});
 
-	const nin = votes && votes.length != 0 ? votes.map(v => v.post_id) : [];
+	const nin = votes && votes.length != 0 ? votes.map(v => v.postId) : [];
 
 	const posts = await Post
 		.find({
 			_id: {
 				$nin: nin
 			},
-			user_id: {
+			userId: {
 				$ne: user._id
 			},
 			poll: {
diff --git a/src/api/endpoints/posts/polls/vote.ts b/src/api/endpoints/posts/polls/vote.ts
index 16ce76a6fa..e87474ae6e 100644
--- a/src/api/endpoints/posts/polls/vote.ts
+++ b/src/api/endpoints/posts/polls/vote.ts
@@ -17,9 +17,9 @@ import { publishPostStream } from '../../../event';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get votee
 	const post = await Post.findOne({
@@ -43,8 +43,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// if already voted
 	const exist = await Vote.findOne({
-		post_id: post._id,
-		user_id: user._id
+		postId: post._id,
+		userId: user._id
 	});
 
 	if (exist !== null) {
@@ -53,9 +53,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create vote
 	await Vote.insert({
-		created_at: new Date(),
-		post_id: post._id,
-		user_id: user._id,
+		createdAt: new Date(),
+		postId: post._id,
+		userId: user._id,
 		choice: choice
 	});
 
@@ -73,27 +73,27 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	publishPostStream(post._id, 'poll_voted');
 
 	// Notify
-	notify(post.user_id, user._id, 'poll_vote', {
-		post_id: post._id,
+	notify(post.userId, user._id, 'poll_vote', {
+		postId: post._id,
 		choice: choice
 	});
 
 	// Fetch watchers
 	Watching
 		.find({
-			post_id: post._id,
-			user_id: { $ne: user._id },
+			postId: post._id,
+			userId: { $ne: user._id },
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
+			deletedAt: { $exists: false }
 		}, {
 			fields: {
-				user_id: true
+				userId: true
 			}
 		})
 		.then(watchers => {
 			watchers.forEach(watcher => {
-				notify(watcher.user_id, user._id, 'poll_vote', {
-					post_id: post._id,
+				notify(watcher.userId, user._id, 'poll_vote', {
+					postId: post._id,
 					choice: choice
 				});
 			});
diff --git a/src/api/endpoints/posts/reactions.ts b/src/api/endpoints/posts/reactions.ts
index feb140ab41..f753ba7c29 100644
--- a/src/api/endpoints/posts/reactions.ts
+++ b/src/api/endpoints/posts/reactions.ts
@@ -13,9 +13,9 @@ import Reaction, { pack } from '../../models/post-reaction';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
@@ -41,8 +41,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	// Issue query
 	const reactions = await Reaction
 		.find({
-			post_id: post._id,
-			deleted_at: { $exists: false }
+			postId: post._id,
+			deletedAt: { $exists: false }
 		}, {
 			limit: limit,
 			skip: offset,
diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts
index f77afed40c..7031d28e56 100644
--- a/src/api/endpoints/posts/reactions/create.ts
+++ b/src/api/endpoints/posts/reactions/create.ts
@@ -18,9 +18,9 @@ import { publishPostStream, pushSw } from '../../../event';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get 'reaction' parameter
 	const [reaction, reactionErr] = $(params.reaction).string().or([
@@ -46,15 +46,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	// Myself
-	if (post.user_id.equals(user._id)) {
+	if (post.userId.equals(user._id)) {
 		return rej('cannot react to my post');
 	}
 
 	// if already reacted
 	const exist = await Reaction.findOne({
-		post_id: post._id,
-		user_id: user._id,
-		deleted_at: { $exists: false }
+		postId: post._id,
+		userId: user._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -63,9 +63,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Create reaction
 	await Reaction.insert({
-		created_at: new Date(),
-		post_id: post._id,
-		user_id: user._id,
+		createdAt: new Date(),
+		postId: post._id,
+		userId: user._id,
 		reaction: reaction
 	});
 
@@ -83,33 +83,33 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	publishPostStream(post._id, 'reacted');
 
 	// Notify
-	notify(post.user_id, user._id, 'reaction', {
-		post_id: post._id,
+	notify(post.userId, user._id, 'reaction', {
+		postId: post._id,
 		reaction: reaction
 	});
 
-	pushSw(post.user_id, 'reaction', {
-		user: await packUser(user, post.user_id),
-		post: await packPost(post, post.user_id),
+	pushSw(post.userId, 'reaction', {
+		user: await packUser(user, post.userId),
+		post: await packPost(post, post.userId),
 		reaction: reaction
 	});
 
 	// Fetch watchers
 	Watching
 		.find({
-			post_id: post._id,
-			user_id: { $ne: user._id },
+			postId: post._id,
+			userId: { $ne: user._id },
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
+			deletedAt: { $exists: false }
 		}, {
 			fields: {
-				user_id: true
+				userId: true
 			}
 		})
 		.then(watchers => {
 			watchers.forEach(watcher => {
-				notify(watcher.user_id, user._id, 'reaction', {
-					post_id: post._id,
+				notify(watcher.userId, user._id, 'reaction', {
+					postId: post._id,
 					reaction: reaction
 				});
 			});
diff --git a/src/api/endpoints/posts/reactions/delete.ts b/src/api/endpoints/posts/reactions/delete.ts
index 922c57ab18..18fdabcdc2 100644
--- a/src/api/endpoints/posts/reactions/delete.ts
+++ b/src/api/endpoints/posts/reactions/delete.ts
@@ -14,9 +14,9 @@ import Post from '../../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Fetch unreactee
 	const post = await Post.findOne({
@@ -29,9 +29,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// if already unreacted
 	const exist = await Reaction.findOne({
-		post_id: post._id,
-		user_id: user._id,
-		deleted_at: { $exists: false }
+		postId: post._id,
+		userId: user._id,
+		deletedAt: { $exists: false }
 	});
 
 	if (exist === null) {
@@ -43,7 +43,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: exist._id
 	}, {
 			$set: {
-				deleted_at: new Date()
+				deletedAt: new Date()
 			}
 		});
 
diff --git a/src/api/endpoints/posts/replies.ts b/src/api/endpoints/posts/replies.ts
index 613c4fa24c..db021505fc 100644
--- a/src/api/endpoints/posts/replies.ts
+++ b/src/api/endpoints/posts/replies.ts
@@ -12,9 +12,9 @@ import Post, { pack } from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
@@ -39,7 +39,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Issue query
 	const replies = await Post
-		.find({ reply_id: post._id }, {
+		.find({ replyId: post._id }, {
 			limit: limit,
 			skip: offset,
 			sort: {
diff --git a/src/api/endpoints/posts/reposts.ts b/src/api/endpoints/posts/reposts.ts
index 89ab0e3d55..c1645117f0 100644
--- a/src/api/endpoints/posts/reposts.ts
+++ b/src/api/endpoints/posts/reposts.ts
@@ -12,9 +12,9 @@ import Post, { pack } from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
@@ -47,7 +47,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		_id: -1
 	};
 	const query = {
-		repost_id: post._id
+		repostId: post._id
 	} as any;
 	if (sinceId) {
 		sort._id = 1;
diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts
index a36d1178a5..e7906c95c8 100644
--- a/src/api/endpoints/posts/search.ts
+++ b/src/api/endpoints/posts/search.ts
@@ -21,13 +21,13 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [text, textError] = $(params.text).optional.string().$;
 	if (textError) return rej('invalid text param');
 
-	// Get 'include_user_ids' parameter
-	const [includeUserIds = [], includeUserIdsErr] = $(params.include_user_ids).optional.array('id').$;
-	if (includeUserIdsErr) return rej('invalid include_user_ids param');
+	// Get 'include_userIds' parameter
+	const [includeUserIds = [], includeUserIdsErr] = $(params.include_userIds).optional.array('id').$;
+	if (includeUserIdsErr) return rej('invalid include_userIds param');
 
-	// Get 'exclude_user_ids' parameter
-	const [excludeUserIds = [], excludeUserIdsErr] = $(params.exclude_user_ids).optional.array('id').$;
-	if (excludeUserIdsErr) return rej('invalid exclude_user_ids param');
+	// Get 'exclude_userIds' parameter
+	const [excludeUserIds = [], excludeUserIdsErr] = $(params.exclude_userIds).optional.array('id').$;
+	if (excludeUserIdsErr) return rej('invalid exclude_userIds param');
 
 	// Get 'include_user_usernames' parameter
 	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.include_user_usernames).optional.array('string').$;
@@ -81,7 +81,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (includeUserUsernames != null) {
 		const ids = (await Promise.all(includeUserUsernames.map(async (username) => {
 			const _user = await User.findOne({
-				username_lower: username.toLowerCase()
+				usernameLower: username.toLowerCase()
 			});
 			return _user ? _user._id : null;
 		}))).filter(id => id != null);
@@ -92,7 +92,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (excludeUserUsernames != null) {
 		const ids = (await Promise.all(excludeUserUsernames.map(async (username) => {
 			const _user = await User.findOne({
-				username_lower: username.toLowerCase()
+				usernameLower: username.toLowerCase()
 			});
 			return _user ? _user._id : null;
 		}))).filter(id => id != null);
@@ -143,13 +143,13 @@ async function search(
 
 	if (includeUserIds && includeUserIds.length != 0) {
 		push({
-			user_id: {
+			userId: {
 				$in: includeUserIds
 			}
 		});
 	} else if (excludeUserIds && excludeUserIds.length != 0) {
 		push({
-			user_id: {
+			userId: {
 				$nin: excludeUserIds
 			}
 		});
@@ -158,7 +158,7 @@ async function search(
 	if (following != null && me != null) {
 		const ids = await getFriends(me._id, false);
 		push({
-			user_id: following ? {
+			userId: following ? {
 				$in: ids
 			} : {
 				$nin: ids.concat(me._id)
@@ -168,45 +168,45 @@ async function search(
 
 	if (me != null) {
 		const mutes = await Mute.find({
-			muter_id: me._id,
-			deleted_at: { $exists: false }
+			muterId: me._id,
+			deletedAt: { $exists: false }
 		});
-		const mutedUserIds = mutes.map(m => m.mutee_id);
+		const mutedUserIds = mutes.map(m => m.muteeId);
 
 		switch (mute) {
 			case 'mute_all':
 				push({
-					user_id: {
+					userId: {
 						$nin: mutedUserIds
 					},
-					'_reply.user_id': {
+					'_reply.userId': {
 						$nin: mutedUserIds
 					},
-					'_repost.user_id': {
+					'_repost.userId': {
 						$nin: mutedUserIds
 					}
 				});
 				break;
 			case 'mute_related':
 				push({
-					'_reply.user_id': {
+					'_reply.userId': {
 						$nin: mutedUserIds
 					},
-					'_repost.user_id': {
+					'_repost.userId': {
 						$nin: mutedUserIds
 					}
 				});
 				break;
 			case 'mute_direct':
 				push({
-					user_id: {
+					userId: {
 						$nin: mutedUserIds
 					}
 				});
 				break;
 			case 'direct_only':
 				push({
-					user_id: {
+					userId: {
 						$in: mutedUserIds
 					}
 				});
@@ -214,11 +214,11 @@ async function search(
 			case 'related_only':
 				push({
 					$or: [{
-						'_reply.user_id': {
+						'_reply.userId': {
 							$in: mutedUserIds
 						}
 					}, {
-						'_repost.user_id': {
+						'_repost.userId': {
 							$in: mutedUserIds
 						}
 					}]
@@ -227,15 +227,15 @@ async function search(
 			case 'all_only':
 				push({
 					$or: [{
-						user_id: {
+						userId: {
 							$in: mutedUserIds
 						}
 					}, {
-						'_reply.user_id': {
+						'_reply.userId': {
 							$in: mutedUserIds
 						}
 					}, {
-						'_repost.user_id': {
+						'_repost.userId': {
 							$in: mutedUserIds
 						}
 					}]
@@ -247,7 +247,7 @@ async function search(
 	if (reply != null) {
 		if (reply) {
 			push({
-				reply_id: {
+				replyId: {
 					$exists: true,
 					$ne: null
 				}
@@ -255,11 +255,11 @@ async function search(
 		} else {
 			push({
 				$or: [{
-					reply_id: {
+					replyId: {
 						$exists: false
 					}
 				}, {
-					reply_id: null
+					replyId: null
 				}]
 			});
 		}
@@ -268,7 +268,7 @@ async function search(
 	if (repost != null) {
 		if (repost) {
 			push({
-				repost_id: {
+				repostId: {
 					$exists: true,
 					$ne: null
 				}
@@ -276,11 +276,11 @@ async function search(
 		} else {
 			push({
 				$or: [{
-					repost_id: {
+					repostId: {
 						$exists: false
 					}
 				}, {
-					repost_id: null
+					repostId: null
 				}]
 			});
 		}
@@ -289,7 +289,7 @@ async function search(
 	if (media != null) {
 		if (media) {
 			push({
-				media_ids: {
+				mediaIds: {
 					$exists: true,
 					$ne: null
 				}
@@ -297,11 +297,11 @@ async function search(
 		} else {
 			push({
 				$or: [{
-					media_ids: {
+					mediaIds: {
 						$exists: false
 					}
 				}, {
-					media_ids: null
+					mediaIds: null
 				}]
 			});
 		}
@@ -330,7 +330,7 @@ async function search(
 
 	if (sinceDate) {
 		push({
-			created_at: {
+			createdAt: {
 				$gt: new Date(sinceDate)
 			}
 		});
@@ -338,7 +338,7 @@ async function search(
 
 	if (untilDate) {
 		push({
-			created_at: {
+			createdAt: {
 				$lt: new Date(untilDate)
 			}
 		});
diff --git a/src/api/endpoints/posts/show.ts b/src/api/endpoints/posts/show.ts
index 3839490597..bb4bcdb790 100644
--- a/src/api/endpoints/posts/show.ts
+++ b/src/api/endpoints/posts/show.ts
@@ -12,9 +12,9 @@ import Post, { pack } from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'post_id' parameter
-	const [postId, postIdErr] = $(params.post_id).id().$;
-	if (postIdErr) return rej('invalid post_id param');
+	// Get 'postId' parameter
+	const [postId, postIdErr] = $(params.postId).id().$;
+	if (postIdErr) return rej('invalid postId param');
 
 	// Get post
 	const post = await Post.findOne({
diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts
index c41cfdb8bd..c7cb8032e3 100644
--- a/src/api/endpoints/posts/timeline.ts
+++ b/src/api/endpoints/posts/timeline.ts
@@ -49,17 +49,17 @@ module.exports = async (params, user, app) => {
 
 		// Watchしているチャンネルを取得
 		watchingChannelIds: ChannelWatching.find({
-			user_id: user._id,
+			userId: user._id,
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
-		}).then(watches => watches.map(w => w.channel_id)),
+			deletedAt: { $exists: false }
+		}).then(watches => watches.map(w => w.channelId)),
 
 		// ミュートしているユーザーを取得
 		mutedUserIds: Mute.find({
-			muter_id: user._id,
+			muterId: user._id,
 			// 削除されたドキュメントは除く
-			deleted_at: { $exists: false }
-		}).then(ms => ms.map(m => m.mutee_id))
+			deletedAt: { $exists: false }
+		}).then(ms => ms.map(m => m.muteeId))
 	});
 
 	//#region Construct query
@@ -70,31 +70,31 @@ module.exports = async (params, user, app) => {
 	const query = {
 		$or: [{
 			// フォローしている人のタイムラインへの投稿
-			user_id: {
+			userId: {
 				$in: followingIds
 			},
 			// 「タイムラインへの」投稿に限定するためにチャンネルが指定されていないもののみに限る
 			$or: [{
-				channel_id: {
+				channelId: {
 					$exists: false
 				}
 			}, {
-				channel_id: null
+				channelId: null
 			}]
 		}, {
 			// Watchしているチャンネルへの投稿
-			channel_id: {
+			channelId: {
 				$in: watchingChannelIds
 			}
 		}],
 		// mute
-		user_id: {
+		userId: {
 			$nin: mutedUserIds
 		},
-		'_reply.user_id': {
+		'_reply.userId': {
 			$nin: mutedUserIds
 		},
-		'_repost.user_id': {
+		'_repost.userId': {
 			$nin: mutedUserIds
 		},
 	} as any;
@@ -110,11 +110,11 @@ module.exports = async (params, user, app) => {
 		};
 	} else if (sinceDate) {
 		sort._id = 1;
-		query.created_at = {
+		query.createdAt = {
 			$gt: new Date(sinceDate)
 		};
 	} else if (untilDate) {
-		query.created_at = {
+		query.createdAt = {
 			$lt: new Date(untilDate)
 		};
 	}
diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts
index caded92bf5..3f92f06167 100644
--- a/src/api/endpoints/posts/trend.ts
+++ b/src/api/endpoints/posts/trend.ts
@@ -38,7 +38,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	if (pollErr) return rej('invalid poll param');
 
 	const query = {
-		created_at: {
+		createdAt: {
 			$gte: new Date(Date.now() - ms('1days'))
 		},
 		repost_count: {
@@ -47,15 +47,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	} as any;
 
 	if (reply != undefined) {
-		query.reply_id = reply ? { $exists: true, $ne: null } : null;
+		query.replyId = reply ? { $exists: true, $ne: null } : null;
 	}
 
 	if (repost != undefined) {
-		query.repost_id = repost ? { $exists: true, $ne: null } : null;
+		query.repostId = repost ? { $exists: true, $ne: null } : null;
 	}
 
 	if (media != undefined) {
-		query.media_ids = media ? { $exists: true, $ne: null } : null;
+		query.mediaIds = media ? { $exists: true, $ne: null } : null;
 	}
 
 	if (poll != undefined) {
diff --git a/src/api/endpoints/stats.ts b/src/api/endpoints/stats.ts
index a6084cd17a..eee6f48706 100644
--- a/src/api/endpoints/stats.ts
+++ b/src/api/endpoints/stats.ts
@@ -15,7 +15,7 @@ import User from '../models/user';
  *         schema:
  *           type: object
  *           properties:
- *             posts_count:
+ *             postsCount:
  *               description: count of all posts of misskey
  *               type: number
  *             users_count:
@@ -42,7 +42,7 @@ module.exports = params => new Promise(async (res, rej) => {
 		.count();
 
 	res({
-		posts_count: postsCount,
+		postsCount: postsCount,
 		users_count: usersCount
 	});
 });
diff --git a/src/api/endpoints/sw/register.ts b/src/api/endpoints/sw/register.ts
index 99406138db..1542e1dbeb 100644
--- a/src/api/endpoints/sw/register.ts
+++ b/src/api/endpoints/sw/register.ts
@@ -28,11 +28,11 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 
 	// if already subscribed
 	const exist = await Subscription.findOne({
-		user_id: user._id,
+		userId: user._id,
 		endpoint: endpoint,
 		auth: auth,
 		publickey: publickey,
-		deleted_at: { $exists: false }
+		deletedAt: { $exists: false }
 	});
 
 	if (exist !== null) {
@@ -40,7 +40,7 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 	}
 
 	await Subscription.insert({
-		user_id: user._id,
+		userId: user._id,
 		endpoint: endpoint,
 		auth: auth,
 		publickey: publickey
diff --git a/src/api/endpoints/username/available.ts b/src/api/endpoints/username/available.ts
index aac7fadf5a..f23cdbd85a 100644
--- a/src/api/endpoints/username/available.ts
+++ b/src/api/endpoints/username/available.ts
@@ -20,7 +20,7 @@ module.exports = async (params) => new Promise(async (res, rej) => {
 	const exist = await User
 		.count({
 			host: null,
-			username_lower: username.toLowerCase()
+			usernameLower: username.toLowerCase()
 		}, {
 			limit: 1
 		});
diff --git a/src/api/endpoints/users.ts b/src/api/endpoints/users.ts
index 4acc13c281..393c3479c5 100644
--- a/src/api/endpoints/users.ts
+++ b/src/api/endpoints/users.ts
@@ -29,11 +29,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (sort) {
 		if (sort == '+follower') {
 			_sort = {
-				followers_count: -1
+				followersCount: -1
 			};
 		} else if (sort == '-follower') {
 			_sort = {
-				followers_count: 1
+				followersCount: 1
 			};
 		}
 	} else {
diff --git a/src/api/endpoints/users/followers.ts b/src/api/endpoints/users/followers.ts
index b0fb83c683..fc09cfa2c6 100644
--- a/src/api/endpoints/users/followers.ts
+++ b/src/api/endpoints/users/followers.ts
@@ -15,9 +15,9 @@ import getFriends from '../../common/get-friends';
  * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
 	const [iknow = false, iknowErr] = $(params.iknow).optional.boolean().$;
@@ -46,8 +46,8 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Construct query
 	const query = {
-		followee_id: user._id,
-		deleted_at: { $exists: false }
+		followeeId: user._id,
+		deletedAt: { $exists: false }
 	} as any;
 
 	// ログインしていてかつ iknow フラグがあるとき
@@ -55,7 +55,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		// Get my friends
 		const myFriends = await getFriends(me._id);
 
-		query.follower_id = {
+		query.followerId = {
 			$in: myFriends
 		};
 	}
@@ -82,7 +82,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Serialize
 	const users = await Promise.all(following.map(async f =>
-		await pack(f.follower_id, me, { detail: true })));
+		await pack(f.followerId, me, { detail: true })));
 
 	// Response
 	res({
diff --git a/src/api/endpoints/users/following.ts b/src/api/endpoints/users/following.ts
index 8e88431e92..3387dab366 100644
--- a/src/api/endpoints/users/following.ts
+++ b/src/api/endpoints/users/following.ts
@@ -15,9 +15,9 @@ import getFriends from '../../common/get-friends';
  * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'iknow' parameter
 	const [iknow = false, iknowErr] = $(params.iknow).optional.boolean().$;
@@ -46,8 +46,8 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Construct query
 	const query = {
-		follower_id: user._id,
-		deleted_at: { $exists: false }
+		followerId: user._id,
+		deletedAt: { $exists: false }
 	} as any;
 
 	// ログインしていてかつ iknow フラグがあるとき
@@ -55,7 +55,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		// Get my friends
 		const myFriends = await getFriends(me._id);
 
-		query.followee_id = {
+		query.followeeId = {
 			$in: myFriends
 		};
 	}
@@ -82,7 +82,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Serialize
 	const users = await Promise.all(following.map(async f =>
-		await pack(f.followee_id, me, { detail: true })));
+		await pack(f.followeeId, me, { detail: true })));
 
 	// Response
 	res({
diff --git a/src/api/endpoints/users/get_frequently_replied_users.ts b/src/api/endpoints/users/get_frequently_replied_users.ts
index 87f4f77a5b..991c5555b6 100644
--- a/src/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/api/endpoints/users/get_frequently_replied_users.ts
@@ -6,9 +6,9 @@ import Post from '../../models/post';
 import User, { pack } from '../../models/user';
 
 module.exports = (params, me) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
@@ -29,8 +29,8 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Fetch recent posts
 	const recentPosts = await Post.find({
-		user_id: user._id,
-		reply_id: {
+		userId: user._id,
+		replyId: {
 			$exists: true,
 			$ne: null
 		}
@@ -41,7 +41,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		limit: 1000,
 		fields: {
 			_id: false,
-			reply_id: true
+			replyId: true
 		}
 	});
 
@@ -52,15 +52,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	const replyTargetPosts = await Post.find({
 		_id: {
-			$in: recentPosts.map(p => p.reply_id)
+			$in: recentPosts.map(p => p.replyId)
 		},
-		user_id: {
+		userId: {
 			$ne: user._id
 		}
 	}, {
 		fields: {
 			_id: false,
-			user_id: true
+			userId: true
 		}
 	});
 
@@ -68,7 +68,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	// Extract replies from recent posts
 	replyTargetPosts.forEach(post => {
-		const userId = post.user_id.toString();
+		const userId = post.userId.toString();
 		if (repliedUsers[userId]) {
 			repliedUsers[userId]++;
 		} else {
diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts
index 3c84bf0d80..f08be91c4d 100644
--- a/src/api/endpoints/users/posts.ts
+++ b/src/api/endpoints/users/posts.ts
@@ -14,16 +14,16 @@ import User from '../../models/user';
  * @return {Promise<any>}
  */
 module.exports = (params, me) => new Promise(async (res, rej) => {
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).optional.id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).optional.id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter
 	const [username, usernameErr] = $(params.username).optional.string().$;
 	if (usernameErr) return rej('invalid username param');
 
 	if (userId === undefined && username === undefined) {
-		return rej('user_id or pair of username and host is required');
+		return rej('userId or pair of username and host is required');
 	}
 
 	// Get 'host' parameter
@@ -31,7 +31,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (hostErr) return rej('invalid host param');
 
 	if (userId === undefined && host === undefined) {
-		return rej('user_id or pair of username and host is required');
+		return rej('userId or pair of username and host is required');
 	}
 
 	// Get 'include_replies' parameter
@@ -69,7 +69,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	const q = userId !== undefined
 		? { _id: userId }
-		: { username_lower: username.toLowerCase(), host_lower: getHostLower(host) } ;
+		: { usernameLower: username.toLowerCase(), hostLower: getHostLower(host) } ;
 
 	// Lookup user
 	const user = await User.findOne(q, {
@@ -88,7 +88,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	};
 
 	const query = {
-		user_id: user._id
+		userId: user._id
 	} as any;
 
 	if (sinceId) {
@@ -102,21 +102,21 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		};
 	} else if (sinceDate) {
 		sort._id = 1;
-		query.created_at = {
+		query.createdAt = {
 			$gt: new Date(sinceDate)
 		};
 	} else if (untilDate) {
-		query.created_at = {
+		query.createdAt = {
 			$lt: new Date(untilDate)
 		};
 	}
 
 	if (!includeReplies) {
-		query.reply_id = null;
+		query.replyId = null;
 	}
 
 	if (withMedia) {
-		query.media_ids = {
+		query.mediaIds = {
 			$exists: true,
 			$ne: null
 		};
diff --git a/src/api/endpoints/users/recommendation.ts b/src/api/endpoints/users/recommendation.ts
index 45d90f422b..c5297cdc50 100644
--- a/src/api/endpoints/users/recommendation.ts
+++ b/src/api/endpoints/users/recommendation.ts
@@ -32,7 +32,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			},
 			$or: [
 				{
-					'account.last_used_at': {
+					'account.lastUsedAt': {
 						$gte: new Date(Date.now() - ms('7days'))
 					}
 				}, {
@@ -43,7 +43,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			limit: limit,
 			skip: offset,
 			sort: {
-				followers_count: -1
+				followersCount: -1
 			}
 		});
 
diff --git a/src/api/endpoints/users/search.ts b/src/api/endpoints/users/search.ts
index 39e2ff9890..1cc25e61b8 100644
--- a/src/api/endpoints/users/search.ts
+++ b/src/api/endpoints/users/search.ts
@@ -41,7 +41,7 @@ async function byNative(res, rej, me, query, offset, max) {
 	const users = await User
 		.find({
 			$or: [{
-				username_lower: new RegExp(escapedQuery.replace('@', '').toLowerCase())
+				usernameLower: new RegExp(escapedQuery.replace('@', '').toLowerCase())
 			}, {
 				name: new RegExp(escapedQuery)
 			}]
diff --git a/src/api/endpoints/users/search_by_username.ts b/src/api/endpoints/users/search_by_username.ts
index 9c5e1905aa..24e9c98e78 100644
--- a/src/api/endpoints/users/search_by_username.ts
+++ b/src/api/endpoints/users/search_by_username.ts
@@ -26,7 +26,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 	const users = await User
 		.find({
-			username_lower: new RegExp(query.toLowerCase())
+			usernameLower: new RegExp(query.toLowerCase())
 		}, {
 			limit: limit,
 			skip: offset
diff --git a/src/api/endpoints/users/show.ts b/src/api/endpoints/users/show.ts
index 78df23f339..16411dddc6 100644
--- a/src/api/endpoints/users/show.ts
+++ b/src/api/endpoints/users/show.ts
@@ -56,9 +56,9 @@ function webFingerAndVerify(query, verifier) {
 module.exports = (params, me) => new Promise(async (res, rej) => {
 	let user;
 
-	// Get 'user_id' parameter
-	const [userId, userIdErr] = $(params.user_id).optional.id().$;
-	if (userIdErr) return rej('invalid user_id param');
+	// Get 'userId' parameter
+	const [userId, userIdErr] = $(params.userId).optional.id().$;
+	if (userIdErr) return rej('invalid userId param');
 
 	// Get 'username' parameter
 	const [username, usernameErr] = $(params.username).optional.string().$;
@@ -69,25 +69,25 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	if (hostErr) return rej('invalid username param');
 
 	if (userId === undefined && typeof username !== 'string') {
-		return rej('user_id or pair of username and host is required');
+		return rej('userId or pair of username and host is required');
 	}
 
 	// Lookup user
 	if (typeof host === 'string') {
-		const username_lower = username.toLowerCase();
-		const host_lower_ascii = toASCII(host).toLowerCase();
-		const host_lower = toUnicode(host_lower_ascii);
+		const usernameLower = username.toLowerCase();
+		const hostLower_ascii = toASCII(host).toLowerCase();
+		const hostLower = toUnicode(hostLower_ascii);
 
-		user = await findUser({ username_lower, host_lower });
+		user = await findUser({ usernameLower, hostLower });
 
 		if (user === null) {
-			const acct_lower = `${username_lower}@${host_lower_ascii}`;
+			const acct_lower = `${usernameLower}@${hostLower_ascii}`;
 			let activityStreams;
 			let finger;
-			let followers_count;
-			let following_count;
+			let followersCount;
+			let followingCount;
 			let likes_count;
-			let posts_count;
+			let postsCount;
 
 			if (!validateUsername(username)) {
 				return rej('username validation failed');
@@ -122,7 +122,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 					activityStreams['@context'] === 'https://www.w3.org/ns/activitystreams') &&
 				activityStreams.type === 'Person' &&
 				typeof activityStreams.preferredUsername === 'string' &&
-				activityStreams.preferredUsername.toLowerCase() === username_lower &&
+				activityStreams.preferredUsername.toLowerCase() === usernameLower &&
 				isValidName(activityStreams.name) &&
 				isValidDescription(activityStreams.summary)
 			)) {
@@ -130,7 +130,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			}
 
 			try {
-				[followers_count, following_count, likes_count, posts_count] = await Promise.all([
+				[followersCount, followingCount, likes_count, postsCount] = await Promise.all([
 					getCollectionCount(activityStreams.followers),
 					getCollectionCount(activityStreams.following),
 					getCollectionCount(activityStreams.liked),
@@ -145,21 +145,21 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 			// Create user
 			user = await User.insert({
-				avatar_id: null,
-				banner_id: null,
-				created_at: new Date(),
+				avatarId: null,
+				bannerId: null,
+				createdAt: new Date(),
 				description: summaryDOM.textContent,
-				followers_count,
-				following_count,
+				followersCount,
+				followingCount,
 				name: activityStreams.name,
-				posts_count,
+				postsCount,
 				likes_count,
 				liked_count: 0,
-				drive_capacity: 1073741824, // 1GB
+				driveCapacity: 1073741824, // 1GB
 				username: username,
-				username_lower,
+				usernameLower,
 				host: toUnicode(finger.subject.replace(/^.*?@/, '')),
-				host_lower,
+				hostLower,
 				account: {
 					uri: activityStreams.id,
 				},
@@ -182,18 +182,18 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 
 			User.update({ _id: user._id }, {
 				$set: {
-					avatar_id: icon._id,
-					banner_id: image._id,
+					avatarId: icon._id,
+					bannerId: image._id,
 				},
 			});
 
-			user.avatar_id = icon._id;
-			user.banner_id = icon._id;
+			user.avatarId = icon._id;
+			user.bannerId = icon._id;
 		}
 	} else {
 		const q = userId !== undefined
 			? { _id: userId }
-			: { username_lower: username.toLowerCase(), host: null };
+			: { usernameLower: username.toLowerCase(), host: null };
 
 		user = await findUser(q);
 
diff --git a/src/api/models/channel-watching.ts b/src/api/models/channel-watching.ts
index 23886d0c76..ec0c8135dc 100644
--- a/src/api/models/channel-watching.ts
+++ b/src/api/models/channel-watching.ts
@@ -9,6 +9,6 @@ export interface IChannelWatching {
 	_id: mongo.ObjectID;
 	createdAt: Date;
 	deletedAt: Date;
-	channel_id: mongo.ObjectID;
+	channelId: mongo.ObjectID;
 	userId: mongo.ObjectID;
 }
diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts
index a753a4ebad..aab21db070 100644
--- a/src/api/models/channel.ts
+++ b/src/api/models/channel.ts
@@ -63,7 +63,7 @@ export const pack = (
 		//#region Watchしているかどうか
 		const watch = await Watching.findOne({
 			userId: meId,
-			channel_id: _channel.id,
+			channelId: _channel.id,
 			deletedAt: { $exists: false }
 		});
 
diff --git a/src/api/models/messaging-message.ts b/src/api/models/messaging-message.ts
index 026b23cf36..9a2f813879 100644
--- a/src/api/models/messaging-message.ts
+++ b/src/api/models/messaging-message.ts
@@ -66,16 +66,16 @@ export const pack = (
 	}
 
 	// Populate user
-	_message.user = await packUser(_message.user_id, me);
+	_message.user = await packUser(_message.userId, me);
 
-	if (_message.file_id) {
+	if (_message.fileId) {
 		// Populate file
-		_message.file = await packFile(_message.file_id);
+		_message.file = await packFile(_message.fileId);
 	}
 
 	if (opts.populateRecipient) {
 		// Populate recipient
-		_message.recipient = await packUser(_message.recipient_id, me);
+		_message.recipient = await packUser(_message.recipientId, me);
 	}
 
 	resolve(_message);
diff --git a/src/api/models/notification.ts b/src/api/models/notification.ts
index fa7049d312..910f539479 100644
--- a/src/api/models/notification.ts
+++ b/src/api/models/notification.ts
@@ -9,7 +9,7 @@ export default Notification;
 
 export interface INotification {
 	_id: mongo.ObjectID;
-	created_at: Date;
+	createdAt: Date;
 
 	/**
 	 * 通知の受信者
@@ -19,7 +19,7 @@ export interface INotification {
 	/**
 	 * 通知の受信者
 	 */
-	notifiee_id: mongo.ObjectID;
+	notifieeId: mongo.ObjectID;
 
 	/**
 	 * イニシエータ(initiator)、Origin。通知を行う原因となったユーザー
@@ -29,7 +29,7 @@ export interface INotification {
 	/**
 	 * イニシエータ(initiator)、Origin。通知を行う原因となったユーザー
 	 */
-	notifier_id: mongo.ObjectID;
+	notifierId: mongo.ObjectID;
 
 	/**
 	 * 通知の種類。
@@ -46,7 +46,7 @@ export interface INotification {
 	/**
 	 * 通知が読まれたかどうか
 	 */
-	is_read: Boolean;
+	isRead: Boolean;
 }
 
 /**
@@ -75,15 +75,15 @@ export const pack = (notification: any) => new Promise<any>(async (resolve, reje
 	_notification.id = _notification._id;
 	delete _notification._id;
 
-	// Rename notifier_id to user_id
-	_notification.user_id = _notification.notifier_id;
-	delete _notification.notifier_id;
+	// Rename notifierId to userId
+	_notification.userId = _notification.notifierId;
+	delete _notification.notifierId;
 
-	const me = _notification.notifiee_id;
-	delete _notification.notifiee_id;
+	const me = _notification.notifieeId;
+	delete _notification.notifieeId;
 
 	// Populate notifier
-	_notification.user = await packUser(_notification.user_id, me);
+	_notification.user = await packUser(_notification.userId, me);
 
 	switch (_notification.type) {
 		case 'follow':
@@ -96,7 +96,7 @@ export const pack = (notification: any) => new Promise<any>(async (resolve, reje
 		case 'reaction':
 		case 'poll_vote':
 			// Populate post
-			_notification.post = await packPost(_notification.post_id, me);
+			_notification.post = await packPost(_notification.postId, me);
 			break;
 		default:
 			console.error(`Unknown type: ${_notification.type}`);
diff --git a/src/api/models/othello-game.ts b/src/api/models/othello-game.ts
index b9e57632d4..70e0c696c8 100644
--- a/src/api/models/othello-game.ts
+++ b/src/api/models/othello-game.ts
@@ -97,10 +97,10 @@ export const pack = (
 	}
 
 	// Populate user
-	_game.user1 = await packUser(_game.user1_id, meId);
-	_game.user2 = await packUser(_game.user2_id, meId);
-	if (_game.winner_id) {
-		_game.winner = await packUser(_game.winner_id, meId);
+	_game.user1 = await packUser(_game.user1Id, meId);
+	_game.user2 = await packUser(_game.user2Id, meId);
+	if (_game.winnerId) {
+		_game.winner = await packUser(_game.winnerId, meId);
 	} else {
 		_game.winner = null;
 	}
diff --git a/src/api/models/othello-matching.ts b/src/api/models/othello-matching.ts
index 9c84d7fb9f..8beedf72cf 100644
--- a/src/api/models/othello-matching.ts
+++ b/src/api/models/othello-matching.ts
@@ -37,8 +37,8 @@ export const pack = (
 	delete _matching._id;
 
 	// Populate user
-	_matching.parent = await packUser(_matching.parent_id, meId);
-	_matching.child = await packUser(_matching.child_id, meId);
+	_matching.parent = await packUser(_matching.parentId, meId);
+	_matching.child = await packUser(_matching.childId, meId);
 
 	resolve(_matching);
 });
diff --git a/src/api/models/post-reaction.ts b/src/api/models/post-reaction.ts
index f581f01535..82613eb262 100644
--- a/src/api/models/post-reaction.ts
+++ b/src/api/models/post-reaction.ts
@@ -47,7 +47,7 @@ export const pack = (
 	delete _reaction._id;
 
 	// Populate user
-	_reaction.user = await packUser(_reaction.user_id, me);
+	_reaction.user = await packUser(_reaction.userId, me);
 
 	resolve(_reaction);
 });
diff --git a/src/api/models/post.ts b/src/api/models/post.ts
index fc44256516..4ab840b5ed 100644
--- a/src/api/models/post.ts
+++ b/src/api/models/post.ts
@@ -100,21 +100,21 @@ export const pack = async (
 	}
 
 	// Populate user
-	_post.user = packUser(_post.user_id, meId);
+	_post.user = packUser(_post.userId, meId);
 
 	// Populate app
-	if (_post.app_id) {
-		_post.app = packApp(_post.app_id);
+	if (_post.appId) {
+		_post.app = packApp(_post.appId);
 	}
 
 	// Populate channel
-	if (_post.channel_id) {
-		_post.channel = packChannel(_post.channel_id);
+	if (_post.channelId) {
+		_post.channel = packChannel(_post.channelId);
 	}
 
 	// Populate media
-	if (_post.media_ids) {
-		_post.media = Promise.all(_post.media_ids.map(fileId =>
+	if (_post.mediaIds) {
+		_post.media = Promise.all(_post.mediaIds.map(fileId =>
 			packFile(fileId)
 		));
 	}
@@ -124,7 +124,7 @@ export const pack = async (
 		// Get previous post info
 		_post.prev = (async () => {
 			const prev = await Post.findOne({
-				user_id: _post.user_id,
+				userId: _post.userId,
 				_id: {
 					$lt: id
 				}
@@ -142,7 +142,7 @@ export const pack = async (
 		// Get next post info
 		_post.next = (async () => {
 			const next = await Post.findOne({
-				user_id: _post.user_id,
+				userId: _post.userId,
 				_id: {
 					$gt: id
 				}
@@ -157,16 +157,16 @@ export const pack = async (
 			return next ? next._id : null;
 		})();
 
-		if (_post.reply_id) {
+		if (_post.replyId) {
 			// Populate reply to post
-			_post.reply = pack(_post.reply_id, meId, {
+			_post.reply = pack(_post.replyId, meId, {
 				detail: false
 			});
 		}
 
-		if (_post.repost_id) {
+		if (_post.repostId) {
 			// Populate repost
-			_post.repost = pack(_post.repost_id, meId, {
+			_post.repost = pack(_post.repostId, meId, {
 				detail: _post.text == null
 			});
 		}
@@ -176,8 +176,8 @@ export const pack = async (
 			_post.poll = (async (poll) => {
 				const vote = await Vote
 					.findOne({
-						user_id: meId,
-						post_id: id
+						userId: meId,
+						postId: id
 					});
 
 				if (vote != null) {
@@ -196,9 +196,9 @@ export const pack = async (
 			_post.my_reaction = (async () => {
 				const reaction = await Reaction
 					.findOne({
-						user_id: meId,
-						post_id: id,
-						deleted_at: { $exists: false }
+						userId: meId,
+						postId: id,
+						deletedAt: { $exists: false }
 					});
 
 				if (reaction) {
diff --git a/src/api/models/user.ts b/src/api/models/user.ts
index 9aa7c4efae..8c68b06dfa 100644
--- a/src/api/models/user.ts
+++ b/src/api/models/user.ts
@@ -47,24 +47,25 @@ export type ILocalAccount = {
 	token: string;
 	twitter: {
 		accessToken: string;
-		access_token_secret: string;
-		user_id: string;
-		screen_name: string;
+		accessTokenSecret: string;
+		userId: string;
+		screenName: string;
 	};
 	line: {
-		user_id: string;
+		userId: string;
 	};
 	profile: {
 		location: string;
 		birthday: string; // 'YYYY-MM-DD'
 		tags: string[];
 	};
-	last_used_at: Date;
-	is_bot: boolean;
-	is_pro: boolean;
-	two_factor_secret: string;
-	two_factor_enabled: boolean;
-	client_settings: any;
+	lastUsedAt: Date;
+	isBot: boolean;
+	isPro: boolean;
+	twoFactorSecret: string;
+	twoFactorEnabled: boolean;
+	twoFactorTempSecret: string;
+	clientSettings: any;
 	settings: any;
 };
 
@@ -74,33 +75,33 @@ export type IRemoteAccount = {
 
 export type IUser = {
 	_id: mongo.ObjectID;
-	created_at: Date;
-	deleted_at: Date;
-	followers_count: number;
-	following_count: number;
+	createdAt: Date;
+	deletedAt: Date;
+	followersCount: number;
+	followingCount: number;
 	name: string;
-	posts_count: number;
-	drive_capacity: number;
+	postsCount: number;
+	driveCapacity: number;
 	username: string;
-	username_lower: string;
-	avatar_id: mongo.ObjectID;
-	banner_id: mongo.ObjectID;
+	usernameLower: string;
+	avatarId: mongo.ObjectID;
+	bannerId: mongo.ObjectID;
 	data: any;
 	description: string;
 	latest_post: IPost;
-	pinned_post_id: mongo.ObjectID;
-	is_suspended: boolean;
+	pinnedPostId: mongo.ObjectID;
+	isSuspended: boolean;
 	keywords: string[];
 	host: string;
-	host_lower: string;
+	hostLower: string;
 	account: ILocalAccount | IRemoteAccount;
 };
 
 export function init(user): IUser {
 	user._id = new mongo.ObjectID(user._id);
-	user.avatar_id = new mongo.ObjectID(user.avatar_id);
-	user.banner_id = new mongo.ObjectID(user.banner_id);
-	user.pinned_post_id = new mongo.ObjectID(user.pinned_post_id);
+	user.avatarId = new mongo.ObjectID(user.avatarId);
+	user.bannerId = new mongo.ObjectID(user.bannerId);
+	user.pinnedPostId = new mongo.ObjectID(user.pinnedPostId);
 	return user;
 }
 
@@ -131,7 +132,7 @@ export const pack = (
 	const fields = opts.detail ? {
 	} : {
 		'account.settings': false,
-		'account.client_settings': false,
+		'account.clientSettings': false,
 		'account.profile': false,
 		'account.keywords': false,
 		'account.domains': false
@@ -173,12 +174,12 @@ export const pack = (
 		delete _user.account.keypair;
 		delete _user.account.password;
 		delete _user.account.token;
-		delete _user.account.two_factor_temp_secret;
-		delete _user.account.two_factor_secret;
-		delete _user.username_lower;
+		delete _user.account.twoFactorTempSecret;
+		delete _user.account.twoFactorSecret;
+		delete _user.usernameLower;
 		if (_user.account.twitter) {
-			delete _user.account.twitter.access_token;
-			delete _user.account.twitter.access_token_secret;
+			delete _user.account.twitter.accessToken;
+			delete _user.account.twitter.accessTokenSecret;
 		}
 		delete _user.account.line;
 
@@ -186,36 +187,36 @@ export const pack = (
 		if (!opts.includeSecrets) {
 			delete _user.account.email;
 			delete _user.account.settings;
-			delete _user.account.client_settings;
+			delete _user.account.clientSettings;
 		}
 
 		if (!opts.detail) {
-			delete _user.account.two_factor_enabled;
+			delete _user.account.twoFactorEnabled;
 		}
 	}
 
-	_user.avatar_url = _user.avatar_id != null
-		? `${config.drive_url}/${_user.avatar_id}`
+	_user.avatar_url = _user.avatarId != null
+		? `${config.drive_url}/${_user.avatarId}`
 		: `${config.drive_url}/default-avatar.jpg`;
 
-	_user.banner_url = _user.banner_id != null
-		? `${config.drive_url}/${_user.banner_id}`
+	_user.banner_url = _user.bannerId != null
+		? `${config.drive_url}/${_user.bannerId}`
 		: null;
 
 	if (!meId || !meId.equals(_user.id) || !opts.detail) {
-		delete _user.avatar_id;
-		delete _user.banner_id;
+		delete _user.avatarId;
+		delete _user.bannerId;
 
-		delete _user.drive_capacity;
+		delete _user.driveCapacity;
 	}
 
 	if (meId && !meId.equals(_user.id)) {
 		// Whether the user is following
 		_user.is_following = (async () => {
 			const follow = await Following.findOne({
-				follower_id: meId,
-				followee_id: _user.id,
-				deleted_at: { $exists: false }
+				followerId: meId,
+				followeeId: _user.id,
+				deletedAt: { $exists: false }
 			});
 			return follow !== null;
 		})();
@@ -223,9 +224,9 @@ export const pack = (
 		// Whether the user is followed
 		_user.is_followed = (async () => {
 			const follow2 = await Following.findOne({
-				follower_id: _user.id,
-				followee_id: meId,
-				deleted_at: { $exists: false }
+				followerId: _user.id,
+				followeeId: meId,
+				deletedAt: { $exists: false }
 			});
 			return follow2 !== null;
 		})();
@@ -233,18 +234,18 @@ export const pack = (
 		// Whether the user is muted
 		_user.is_muted = (async () => {
 			const mute = await Mute.findOne({
-				muter_id: meId,
-				mutee_id: _user.id,
-				deleted_at: { $exists: false }
+				muterId: meId,
+				muteeId: _user.id,
+				deletedAt: { $exists: false }
 			});
 			return mute !== null;
 		})();
 	}
 
 	if (opts.detail) {
-		if (_user.pinned_post_id) {
+		if (_user.pinnedPostId) {
 			// Populate pinned post
-			_user.pinned_post = packPost(_user.pinned_post_id, meId, {
+			_user.pinnedPost = packPost(_user.pinnedPostId, meId, {
 				detail: true
 			});
 		}
@@ -254,16 +255,16 @@ export const pack = (
 
 			// Get following you know count
 			_user.following_you_know_count = Following.count({
-				followee_id: { $in: myFollowingIds },
-				follower_id: _user.id,
-				deleted_at: { $exists: false }
+				followeeId: { $in: myFollowingIds },
+				followerId: _user.id,
+				deletedAt: { $exists: false }
 			});
 
 			// Get followers you know count
 			_user.followers_you_know_count = Following.count({
-				followee_id: _user.id,
-				follower_id: { $in: myFollowingIds },
-				deleted_at: { $exists: false }
+				followeeId: _user.id,
+				followerId: { $in: myFollowingIds },
+				deletedAt: { $exists: false }
 			});
 		}
 	}
@@ -322,7 +323,7 @@ export const packForAp = (
 		"name": _user.name,
 		"summary": _user.description,
 		"icon": [
-			`${config.drive_url}/${_user.avatar_id}`
+			`${config.drive_url}/${_user.avatarId}`
 		]
 	});
 });
diff --git a/src/api/private/signin.ts b/src/api/private/signin.ts
index 00dcb8afc8..c6b5d19ea6 100644
--- a/src/api/private/signin.ts
+++ b/src/api/private/signin.ts
@@ -32,7 +32,7 @@ export default async (req: express.Request, res: express.Response) => {
 
 	// Fetch user
 	const user: IUser = await User.findOne({
-		username_lower: username.toLowerCase(),
+		usernameLower: username.toLowerCase(),
 		host: null
 	}, {
 		fields: {
@@ -54,9 +54,9 @@ export default async (req: express.Request, res: express.Response) => {
 	const same = await bcrypt.compare(password, account.password);
 
 	if (same) {
-		if (account.two_factor_enabled) {
+		if (account.twoFactorEnabled) {
 			const verified = (speakeasy as any).totp.verify({
-				secret: account.two_factor_secret,
+				secret: account.twoFactorSecret,
 				encoding: 'base32',
 				token: token
 			});
@@ -79,8 +79,8 @@ export default async (req: express.Request, res: express.Response) => {
 
 	// Append signin history
 	const record = await Signin.insert({
-		created_at: new Date(),
-		user_id: user._id,
+		createdAt: new Date(),
+		userId: user._id,
 		ip: req.ip,
 		headers: req.headers,
 		success: same
diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts
index 29d75b62f9..1304ccb54c 100644
--- a/src/api/private/signup.ts
+++ b/src/api/private/signup.ts
@@ -64,7 +64,7 @@ export default async (req: express.Request, res: express.Response) => {
 	// Fetch exist user that same username
 	const usernameExist = await User
 		.count({
-			username_lower: username.toLowerCase(),
+			usernameLower: username.toLowerCase(),
 			host: null
 		}, {
 			limit: 1
@@ -107,19 +107,19 @@ export default async (req: express.Request, res: express.Response) => {
 
 	// Create account
 	const account: IUser = await User.insert({
-		avatar_id: null,
-		banner_id: null,
-		created_at: new Date(),
+		avatarId: null,
+		bannerId: null,
+		createdAt: new Date(),
 		description: null,
-		followers_count: 0,
-		following_count: 0,
+		followersCount: 0,
+		followingCount: 0,
 		name: name,
-		posts_count: 0,
-		drive_capacity: 1073741824, // 1GB
+		postsCount: 0,
+		driveCapacity: 1073741824, // 1GB
 		username: username,
-		username_lower: username.toLowerCase(),
+		usernameLower: username.toLowerCase(),
 		host: null,
-		host_lower: null,
+		hostLower: null,
 		account: {
 			keypair: generateKeypair(),
 			token: secret,
@@ -139,7 +139,7 @@ export default async (req: express.Request, res: express.Response) => {
 			settings: {
 				auto_watch: true
 			},
-			client_settings: {
+			clientSettings: {
 				home: homeData
 			}
 		}
diff --git a/src/api/service/github.ts b/src/api/service/github.ts
index 1c78267c0f..598f36b0cf 100644
--- a/src/api/service/github.ts
+++ b/src/api/service/github.ts
@@ -9,7 +9,7 @@ module.exports = async (app: express.Application) => {
 	if (config.github_bot == null) return;
 
 	const bot = await User.findOne({
-		username_lower: config.github_bot.username.toLowerCase()
+		usernameLower: config.github_bot.username.toLowerCase()
 	});
 
 	if (bot == null) {
diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts
index c1f2e48a63..67c401efac 100644
--- a/src/api/service/twitter.ts
+++ b/src/api/service/twitter.ts
@@ -128,7 +128,7 @@ module.exports = (app: express.Application) => {
 
 				const user = await User.findOne({
 					host: null,
-					'account.twitter.user_id': result.userId
+					'account.twitter.userId': result.userId
 				});
 
 				if (user == null) {
@@ -155,10 +155,10 @@ module.exports = (app: express.Application) => {
 				}, {
 					$set: {
 						'account.twitter': {
-							access_token: result.accessToken,
-							access_token_secret: result.accessTokenSecret,
-							user_id: result.userId,
-							screen_name: result.screenName
+							accessToken: result.accessToken,
+							accessTokenSecret: result.accessTokenSecret,
+							userId: result.userId,
+							screenName: result.screenName
 						}
 					}
 				});
diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts
index 1ef0f33b4b..291be0824d 100644
--- a/src/api/stream/home.ts
+++ b/src/api/stream/home.ts
@@ -14,10 +14,10 @@ export default async function(request: websocket.request, connection: websocket.
 	subscriber.subscribe(`misskey:user-stream:${user._id}`);
 
 	const mute = await Mute.find({
-		muter_id: user._id,
-		deleted_at: { $exists: false }
+		muterId: user._id,
+		deletedAt: { $exists: false }
 	});
-	const mutedUserIds = mute.map(m => m.mutee_id.toString());
+	const mutedUserIds = mute.map(m => m.muteeId.toString());
 
 	subscriber.on('message', async (channel, data) => {
 		switch (channel.split(':')[1]) {
@@ -26,17 +26,17 @@ export default async function(request: websocket.request, connection: websocket.
 					const x = JSON.parse(data);
 
 					if (x.type == 'post') {
-						if (mutedUserIds.indexOf(x.body.user_id) != -1) {
+						if (mutedUserIds.indexOf(x.body.userId) != -1) {
 							return;
 						}
-						if (x.body.reply != null && mutedUserIds.indexOf(x.body.reply.user_id) != -1) {
+						if (x.body.reply != null && mutedUserIds.indexOf(x.body.reply.userId) != -1) {
 							return;
 						}
-						if (x.body.repost != null && mutedUserIds.indexOf(x.body.repost.user_id) != -1) {
+						if (x.body.repost != null && mutedUserIds.indexOf(x.body.repost.userId) != -1) {
 							return;
 						}
 					} else if (x.type == 'notification') {
-						if (mutedUserIds.indexOf(x.body.user_id) != -1) {
+						if (mutedUserIds.indexOf(x.body.userId) != -1) {
 							return;
 						}
 					}
@@ -74,7 +74,7 @@ export default async function(request: websocket.request, connection: websocket.
 				// Update lastUsedAt
 				User.update({ _id: user._id }, {
 					$set: {
-						'account.last_used_at': new Date()
+						'account.lastUsedAt': new Date()
 					}
 				});
 				break;
diff --git a/src/api/stream/othello-game.ts b/src/api/stream/othello-game.ts
index 45a931c7e7..e48d93cddc 100644
--- a/src/api/stream/othello-game.ts
+++ b/src/api/stream/othello-game.ts
@@ -62,10 +62,10 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function updateSettings(settings) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (game.is_started) return;
-		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
-		if (game.user1_id.equals(user._id) && game.user1_accepted) return;
-		if (game.user2_id.equals(user._id) && game.user2_accepted) return;
+		if (game.isStarted) return;
+		if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) return;
+		if (game.user1Id.equals(user._id) && game.user1Accepted) return;
+		if (game.user2Id.equals(user._id) && game.user2Accepted) return;
 
 		await OthelloGame.update({ _id: gameId }, {
 			$set: {
@@ -79,10 +79,10 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function initForm(form) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (game.is_started) return;
-		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
+		if (game.isStarted) return;
+		if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) return;
 
-		const set = game.user1_id.equals(user._id) ? {
+		const set = game.user1Id.equals(user._id) ? {
 			form1: form
 		} : {
 			form2: form
@@ -93,7 +93,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		});
 
 		publishOthelloGameStream(gameId, 'init-form', {
-			user_id: user._id,
+			userId: user._id,
 			form
 		});
 	}
@@ -101,10 +101,10 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function updateForm(id, value) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (game.is_started) return;
-		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
+		if (game.isStarted) return;
+		if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) return;
 
-		const form = game.user1_id.equals(user._id) ? game.form2 : game.form1;
+		const form = game.user1Id.equals(user._id) ? game.form2 : game.form1;
 
 		const item = form.find(i => i.id == id);
 
@@ -112,7 +112,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 		item.value = value;
 
-		const set = game.user1_id.equals(user._id) ? {
+		const set = game.user1Id.equals(user._id) ? {
 			form2: form
 		} : {
 			form1: form
@@ -123,7 +123,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		});
 
 		publishOthelloGameStream(gameId, 'update-form', {
-			user_id: user._id,
+			userId: user._id,
 			id,
 			value
 		});
@@ -132,7 +132,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function message(message) {
 		message.id = Math.random();
 		publishOthelloGameStream(gameId, 'message', {
-			user_id: user._id,
+			userId: user._id,
 			message
 		});
 	}
@@ -140,36 +140,36 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function accept(accept: boolean) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (game.is_started) return;
+		if (game.isStarted) return;
 
 		let bothAccepted = false;
 
-		if (game.user1_id.equals(user._id)) {
+		if (game.user1Id.equals(user._id)) {
 			await OthelloGame.update({ _id: gameId }, {
 				$set: {
-					user1_accepted: accept
+					user1Accepted: accept
 				}
 			});
 
 			publishOthelloGameStream(gameId, 'change-accepts', {
 				user1: accept,
-				user2: game.user2_accepted
+				user2: game.user2Accepted
 			});
 
-			if (accept && game.user2_accepted) bothAccepted = true;
-		} else if (game.user2_id.equals(user._id)) {
+			if (accept && game.user2Accepted) bothAccepted = true;
+		} else if (game.user2Id.equals(user._id)) {
 			await OthelloGame.update({ _id: gameId }, {
 				$set: {
-					user2_accepted: accept
+					user2Accepted: accept
 				}
 			});
 
 			publishOthelloGameStream(gameId, 'change-accepts', {
-				user1: game.user1_accepted,
+				user1: game.user1Accepted,
 				user2: accept
 			});
 
-			if (accept && game.user1_accepted) bothAccepted = true;
+			if (accept && game.user1Accepted) bothAccepted = true;
 		} else {
 			return;
 		}
@@ -178,8 +178,8 @@ export default function(request: websocket.request, connection: websocket.connec
 			// 3秒後、まだacceptされていたらゲーム開始
 			setTimeout(async () => {
 				const freshGame = await OthelloGame.findOne({ _id: gameId });
-				if (freshGame == null || freshGame.is_started || freshGame.is_ended) return;
-				if (!freshGame.user1_accepted || !freshGame.user2_accepted) return;
+				if (freshGame == null || freshGame.isStarted || freshGame.isEnded) return;
+				if (!freshGame.user1Accepted || !freshGame.user2Accepted) return;
 
 				let bw: number;
 				if (freshGame.settings.bw == 'random') {
@@ -198,8 +198,8 @@ export default function(request: websocket.request, connection: websocket.connec
 
 				await OthelloGame.update({ _id: gameId }, {
 					$set: {
-						started_at: new Date(),
-						is_started: true,
+						startedAt: new Date(),
+						isStarted: true,
 						black: bw,
 						'settings.map': map
 					}
@@ -207,17 +207,17 @@ export default function(request: websocket.request, connection: websocket.connec
 
 				//#region 盤面に最初から石がないなどして始まった瞬間に勝敗が決定する場合があるのでその処理
 				const o = new Othello(map, {
-					isLlotheo: freshGame.settings.is_llotheo,
-					canPutEverywhere: freshGame.settings.can_put_everywhere,
-					loopedBoard: freshGame.settings.looped_board
+					isLlotheo: freshGame.settings.isLlotheo,
+					canPutEverywhere: freshGame.settings.canPutEverywhere,
+					loopedBoard: freshGame.settings.loopedBoard
 				});
 
 				if (o.isEnded) {
 					let winner;
 					if (o.winner === true) {
-						winner = freshGame.black == 1 ? freshGame.user1_id : freshGame.user2_id;
+						winner = freshGame.black == 1 ? freshGame.user1Id : freshGame.user2Id;
 					} else if (o.winner === false) {
-						winner = freshGame.black == 1 ? freshGame.user2_id : freshGame.user1_id;
+						winner = freshGame.black == 1 ? freshGame.user2Id : freshGame.user1Id;
 					} else {
 						winner = null;
 					}
@@ -226,13 +226,13 @@ export default function(request: websocket.request, connection: websocket.connec
 						_id: gameId
 					}, {
 						$set: {
-							is_ended: true,
-							winner_id: winner
+							isEnded: true,
+							winnerId: winner
 						}
 					});
 
 					publishOthelloGameStream(gameId, 'ended', {
-						winner_id: winner,
+						winnerId: winner,
 						game: await pack(gameId, user)
 					});
 				}
@@ -247,14 +247,14 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function set(pos) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (!game.is_started) return;
-		if (game.is_ended) return;
-		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
+		if (!game.isStarted) return;
+		if (game.isEnded) return;
+		if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) return;
 
 		const o = new Othello(game.settings.map, {
-			isLlotheo: game.settings.is_llotheo,
-			canPutEverywhere: game.settings.can_put_everywhere,
-			loopedBoard: game.settings.looped_board
+			isLlotheo: game.settings.isLlotheo,
+			canPutEverywhere: game.settings.canPutEverywhere,
+			loopedBoard: game.settings.loopedBoard
 		});
 
 		game.logs.forEach(log => {
@@ -262,7 +262,7 @@ export default function(request: websocket.request, connection: websocket.connec
 		});
 
 		const myColor =
-			(game.user1_id.equals(user._id) && game.black == 1) || (game.user2_id.equals(user._id) && game.black == 2)
+			(game.user1Id.equals(user._id) && game.black == 1) || (game.user2Id.equals(user._id) && game.black == 2)
 				? true
 				: false;
 
@@ -272,9 +272,9 @@ export default function(request: websocket.request, connection: websocket.connec
 		let winner;
 		if (o.isEnded) {
 			if (o.winner === true) {
-				winner = game.black == 1 ? game.user1_id : game.user2_id;
+				winner = game.black == 1 ? game.user1Id : game.user2Id;
 			} else if (o.winner === false) {
-				winner = game.black == 1 ? game.user2_id : game.user1_id;
+				winner = game.black == 1 ? game.user2Id : game.user1Id;
 			} else {
 				winner = null;
 			}
@@ -293,8 +293,8 @@ export default function(request: websocket.request, connection: websocket.connec
 		}, {
 			$set: {
 				crc32,
-				is_ended: o.isEnded,
-				winner_id: winner
+				isEnded: o.isEnded,
+				winnerId: winner
 			},
 			$push: {
 				logs: log
@@ -307,7 +307,7 @@ export default function(request: websocket.request, connection: websocket.connec
 
 		if (o.isEnded) {
 			publishOthelloGameStream(gameId, 'ended', {
-				winner_id: winner,
+				winnerId: winner,
 				game: await pack(gameId, user)
 			});
 		}
@@ -316,7 +316,7 @@ export default function(request: websocket.request, connection: websocket.connec
 	async function check(crc32) {
 		const game = await OthelloGame.findOne({ _id: gameId });
 
-		if (!game.is_started) return;
+		if (!game.isStarted) return;
 
 		// 互換性のため
 		if (game.crc32 == null) return;
diff --git a/src/api/stream/othello.ts b/src/api/stream/othello.ts
index bd3b4a7637..55c993ec85 100644
--- a/src/api/stream/othello.ts
+++ b/src/api/stream/othello.ts
@@ -18,11 +18,11 @@ export default function(request: websocket.request, connection: websocket.connec
 			case 'ping':
 				if (msg.id == null) return;
 				const matching = await Matching.findOne({
-					parent_id: user._id,
-					child_id: new mongo.ObjectID(msg.id)
+					parentId: user._id,
+					childId: new mongo.ObjectID(msg.id)
 				});
 				if (matching == null) return;
-				publishUserStream(matching.child_id, 'othello_invited', await pack(matching, matching.child_id));
+				publishUserStream(matching.childId, 'othello_invited', await pack(matching, matching.childId));
 				break;
 		}
 	});
diff --git a/src/api/streaming.ts b/src/api/streaming.ts
index a6759e414c..31319fcab6 100644
--- a/src/api/streaming.ts
+++ b/src/api/streaming.ts
@@ -110,7 +110,7 @@ function authenticate(token: string): Promise<IUser> {
 
 			// Fetch user
 			const user: IUser = await User
-				.findOne({ _id: accessToken.user_id });
+				.findOne({ _id: accessToken.userId });
 
 			resolve(user);
 		}
diff --git a/src/common/get-post-summary.ts b/src/common/get-post-summary.ts
index 6e8f65708e..8d0033064f 100644
--- a/src/common/get-post-summary.ts
+++ b/src/common/get-post-summary.ts
@@ -22,7 +22,7 @@ const summarize = (post: any): string => {
 	}
 
 	// 返信のとき
-	if (post.reply_id) {
+	if (post.replyId) {
 		if (post.reply) {
 			summary += ` RE: ${summarize(post.reply)}`;
 		} else {
@@ -31,7 +31,7 @@ const summarize = (post: any): string => {
 	}
 
 	// Repostのとき
-	if (post.repost_id) {
+	if (post.repostId) {
 		if (post.repost) {
 			summary += ` RP: ${summarize(post.repost)}`;
 		} else {
diff --git a/src/common/othello/ai/back.ts b/src/common/othello/ai/back.ts
index 27dbc39529..52f01ff97b 100644
--- a/src/common/othello/ai/back.ts
+++ b/src/common/othello/ai/back.ts
@@ -44,7 +44,7 @@ process.on('message', async msg => {
 		//#region TLに投稿する
 		const game = msg.body;
 		const url = `${conf.url}/othello/${game.id}`;
-		const user = game.user1_id == id ? game.user2 : game.user1;
+		const user = game.user1Id == id ? game.user2 : game.user1;
 		const isSettai = form[0].value === 0;
 		const text = isSettai
 			? `?[${user.name}](${conf.url}/@${user.username})さんの接待を始めました!`
@@ -68,23 +68,23 @@ process.on('message', async msg => {
 		});
 
 		//#region TLに投稿する
-		const user = game.user1_id == id ? game.user2 : game.user1;
+		const user = game.user1Id == id ? game.user2 : game.user1;
 		const isSettai = form[0].value === 0;
 		const text = isSettai
-			? msg.body.winner_id === null
+			? msg.body.winnerId === null
 				? `?[${user.name}](${conf.url}/@${user.username})さんに接待で引き分けました...`
-				: msg.body.winner_id == id
+				: msg.body.winnerId == id
 					? `?[${user.name}](${conf.url}/@${user.username})さんに接待で勝ってしまいました...`
 					: `?[${user.name}](${conf.url}/@${user.username})さんに接待で負けてあげました♪`
-			: msg.body.winner_id === null
+			: msg.body.winnerId === null
 				? `?[${user.name}](${conf.url}/@${user.username})さんと引き分けました~`
-				: msg.body.winner_id == id
+				: msg.body.winnerId == id
 					? `?[${user.name}](${conf.url}/@${user.username})さんに勝ちました♪`
 					: `?[${user.name}](${conf.url}/@${user.username})さんに負けました...`;
 
 		await request.post(`${conf.api_url}/posts/create`, {
 			json: { i,
-				repost_id: post.id,
+				repostId: post.id,
 				text: text
 			}
 		});
@@ -114,9 +114,9 @@ function onGameStarted(g) {
 
 	// オセロエンジン初期化
 	o = new Othello(game.settings.map, {
-		isLlotheo: game.settings.is_llotheo,
-		canPutEverywhere: game.settings.can_put_everywhere,
-		loopedBoard: game.settings.looped_board
+		isLlotheo: game.settings.isLlotheo,
+		canPutEverywhere: game.settings.canPutEverywhere,
+		loopedBoard: game.settings.loopedBoard
 	});
 
 	// 各マスの価値を計算しておく
@@ -141,7 +141,7 @@ function onGameStarted(g) {
 		return count >= 4 ? 1 : 0;
 	});
 
-	botColor = game.user1_id == id && game.black == 1 || game.user2_id == id && game.black == 2;
+	botColor = game.user1Id == id && game.black == 1 || game.user2Id == id && game.black == 2;
 
 	if (botColor) {
 		think();
@@ -188,7 +188,7 @@ function think() {
 		});
 
 		// ロセオならスコアを反転
-		if (game.settings.is_llotheo) score = -score;
+		if (game.settings.isLlotheo) score = -score;
 
 		// 接待ならスコアを反転
 		if (isSettai) score = -score;
@@ -234,7 +234,7 @@ function think() {
 
 			let score;
 
-			if (game.settings.is_llotheo) {
+			if (game.settings.isLlotheo) {
 				// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
 				score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
 			} else {
@@ -317,7 +317,7 @@ function think() {
 
 			let score;
 
-			if (game.settings.is_llotheo) {
+			if (game.settings.isLlotheo) {
 				// 勝ちは勝ちでも、より自分の石を少なくした方が美しい勝ちだと判定する
 				score = o.winner ? base - (o.blackCount * 100) : base - (o.whiteCount * 100);
 			} else {
diff --git a/src/common/othello/ai/front.ts b/src/common/othello/ai/front.ts
index d892afbeda..e5496132f6 100644
--- a/src/common/othello/ai/front.ts
+++ b/src/common/othello/ai/front.ts
@@ -48,12 +48,12 @@ homeStream.on('message', message => {
 	if (msg.type == 'mention' || msg.type == 'reply') {
 		const post = msg.body;
 
-		if (post.user_id == id) return;
+		if (post.userId == id) return;
 
 		// リアクションする
 		request.post(`${conf.api_url}/posts/reactions/create`, {
 			json: { i,
-				post_id: post.id,
+				postId: post.id,
 				reaction: 'love'
 			}
 		});
@@ -62,12 +62,12 @@ homeStream.on('message', message => {
 			if (post.text.indexOf('オセロ') > -1) {
 				request.post(`${conf.api_url}/posts/create`, {
 					json: { i,
-						reply_id: post.id,
+						replyId: post.id,
 						text: '良いですよ~'
 					}
 				});
 
-				invite(post.user_id);
+				invite(post.userId);
 			}
 		}
 	}
@@ -79,12 +79,12 @@ homeStream.on('message', message => {
 			if (message.text.indexOf('オセロ') > -1) {
 				request.post(`${conf.api_url}/messaging/messages/create`, {
 					json: { i,
-						user_id: message.user_id,
+						userId: message.userId,
 						text: '良いですよ~'
 					}
 				});
 
-				invite(message.user_id);
+				invite(message.userId);
 			}
 		}
 	}
@@ -94,7 +94,7 @@ homeStream.on('message', message => {
 function invite(userId) {
 	request.post(`${conf.api_url}/othello/match`, {
 		json: { i,
-			user_id: userId
+			userId: userId
 		}
 	});
 }
@@ -225,7 +225,7 @@ async function onInviteMe(inviter) {
 	const game = await request.post(`${conf.api_url}/othello/match`, {
 		json: {
 			i,
-			user_id: inviter.id
+			userId: inviter.id
 		}
 	});
 
diff --git a/src/common/user/get-summary.ts b/src/common/user/get-summary.ts
index f9b7125e30..b314a5cefb 100644
--- a/src/common/user/get-summary.ts
+++ b/src/common/user/get-summary.ts
@@ -7,7 +7,7 @@ import getAcct from './get-acct';
  */
 export default function(user: IUser): string {
 	let string = `${user.name} (@${getAcct(user)})\n` +
-		`${user.posts_count}投稿、${user.following_count}フォロー、${user.followers_count}フォロワー\n`;
+		`${user.postsCount}投稿、${user.followingCount}フォロー、${user.followersCount}フォロワー\n`;
 
 	if (user.host === null) {
 		const account = user.account as ILocalAccount;
diff --git a/src/config.ts b/src/config.ts
index 6d3e7740b1..0d8df39f44 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -80,7 +80,7 @@ type Source = {
 	};
 	line_bot?: {
 		channel_secret: string;
-		channel_access_token: string;
+		channel_accessToken: string;
 	};
 	analysis?: {
 		mecab_command?: string;
diff --git a/src/tools/analysis/extract-user-domains.ts b/src/tools/analysis/extract-user-domains.ts
index bc120f5c17..0c4249a1b6 100644
--- a/src/tools/analysis/extract-user-domains.ts
+++ b/src/tools/analysis/extract-user-domains.ts
@@ -50,7 +50,7 @@ function extractDomainsOne(id) {
 
 		// Fetch recent posts
 		const recentPosts = await Post.find({
-			user_id: id,
+			userId: id,
 			text: {
 				$exists: true
 			}
diff --git a/src/tools/analysis/extract-user-keywords.ts b/src/tools/analysis/extract-user-keywords.ts
index b99ca93211..08d02e7057 100644
--- a/src/tools/analysis/extract-user-keywords.ts
+++ b/src/tools/analysis/extract-user-keywords.ts
@@ -96,7 +96,7 @@ function extractKeywordsOne(id) {
 
 		// Fetch recent posts
 		const recentPosts = await Post.find({
-			user_id: id,
+			userId: id,
 			text: {
 				$exists: true
 			}
diff --git a/src/tools/analysis/predict-user-interst.ts b/src/tools/analysis/predict-user-interst.ts
index 99bdfa4206..6904daeb07 100644
--- a/src/tools/analysis/predict-user-interst.ts
+++ b/src/tools/analysis/predict-user-interst.ts
@@ -6,7 +6,7 @@ export async function predictOne(id) {
 
 	// TODO: repostなども含める
 	const recentPosts = await Post.find({
-		user_id: id,
+		userId: id,
 		category: {
 			$exists: true
 		}
diff --git a/src/web/app/auth/views/form.vue b/src/web/app/auth/views/form.vue
index d86ed58b38..9d9e8cdb1b 100644
--- a/src/web/app/auth/views/form.vue
+++ b/src/web/app/auth/views/form.vue
@@ -7,7 +7,7 @@
 	<div class="app">
 		<section>
 			<h2>{{ app.name }}</h2>
-			<p class="nid">{{ app.name_id }}</p>
+			<p class="nid">{{ app.nameId }}</p>
 			<p class="description">{{ app.description }}</p>
 		</section>
 		<section>
diff --git a/src/web/app/ch/tags/channel.tag b/src/web/app/ch/tags/channel.tag
index dc4b8e1426..225129088d 100644
--- a/src/web/app/ch/tags/channel.tag
+++ b/src/web/app/ch/tags/channel.tag
@@ -77,7 +77,7 @@
 
 			// チャンネル概要読み込み
 			this.$root.$data.os.api('channels/show', {
-				channel_id: this.id
+				channelId: this.id
 			}).then(channel => {
 				if (fetched) {
 					Progress.done();
@@ -96,7 +96,7 @@
 
 			// 投稿読み込み
 			this.$root.$data.os.api('channels/posts', {
-				channel_id: this.id
+				channelId: this.id
 			}).then(posts => {
 				if (fetched) {
 					Progress.done();
@@ -125,7 +125,7 @@
 			this.posts.unshift(post);
 			this.update();
 
-			if (document.hidden && this.$root.$data.os.isSignedIn && post.user_id !== this.$root.$data.os.i.id) {
+			if (document.hidden && this.$root.$data.os.isSignedIn && post.userId !== this.$root.$data.os.i.id) {
 				this.unreadCount++;
 				document.title = `(${this.unreadCount}) ${this.channel.title} | Misskey`;
 			}
@@ -140,7 +140,7 @@
 
 		this.watch = () => {
 			this.$root.$data.os.api('channels/watch', {
-				channel_id: this.id
+				channelId: this.id
 			}).then(() => {
 				this.channel.is_watching = true;
 				this.update();
@@ -151,7 +151,7 @@
 
 		this.unwatch = () => {
 			this.$root.$data.os.api('channels/unwatch', {
-				channel_id: this.id
+				channelId: this.id
 			}).then(() => {
 				this.channel.is_watching = false;
 				this.update();
@@ -166,8 +166,8 @@
 	<header>
 		<a class="index" @click="reply">{ post.index }:</a>
 		<a class="name" href={ _URL_ + '/@' + acct }><b>{ post.user.name }</b></a>
-		<mk-time time={ post.created_at }/>
-		<mk-time time={ post.created_at } mode="detail"/>
+		<mk-time time={ post.createdAt }/>
+		<mk-time time={ post.createdAt } mode="detail"/>
 		<span>ID:<i>{ acct }</i></span>
 	</header>
 	<div>
@@ -328,9 +328,9 @@
 
 			this.$root.$data.os.api('posts/create', {
 				text: this.$refs.text.value == '' ? undefined : this.$refs.text.value,
-				media_ids: files,
-				reply_id: this.reply ? this.reply.id : undefined,
-				channel_id: this.channel.id
+				mediaIds: files,
+				replyId: this.reply ? this.reply.id : undefined,
+				channelId: this.channel.id
 			}).then(data => {
 				this.clear();
 			}).catch(err => {
diff --git a/src/web/app/common/define-widget.ts b/src/web/app/common/define-widget.ts
index d8d29873a4..27db59b5ee 100644
--- a/src/web/app/common/define-widget.ts
+++ b/src/web/app/common/define-widget.ts
@@ -56,14 +56,14 @@ export default function<T extends object>(data: {
 						id: this.id,
 						data: newProps
 					}).then(() => {
-						(this as any).os.i.account.client_settings.mobile_home.find(w => w.id == this.id).data = newProps;
+						(this as any).os.i.account.clientSettings.mobile_home.find(w => w.id == this.id).data = newProps;
 					});
 				} else {
 					(this as any).api('i/update_home', {
 						id: this.id,
 						data: newProps
 					}).then(() => {
-						(this as any).os.i.account.client_settings.home.find(w => w.id == this.id).data = newProps;
+						(this as any).os.i.account.clientSettings.home.find(w => w.id == this.id).data = newProps;
 					});
 				}
 			}, {
diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts
index 2c6c9988e7..bcb8b60678 100644
--- a/src/web/app/common/mios.ts
+++ b/src/web/app/common/mios.ts
@@ -294,12 +294,12 @@ export default class MiOS extends EventEmitter {
 		const fetched = me => {
 			if (me) {
 				// デフォルトの設定をマージ
-				me.account.client_settings = Object.assign({
+				me.account.clientSettings = Object.assign({
 					fetchOnScroll: true,
 					showMaps: true,
 					showPostFormOnTopOfTl: false,
 					gradientWindowHeader: false
-				}, me.account.client_settings);
+				}, me.account.clientSettings);
 
 				// ローカルストレージにキャッシュ
 				localStorage.setItem('me', JSON.stringify(me));
diff --git a/src/web/app/common/scripts/streaming/home.ts b/src/web/app/common/scripts/streaming/home.ts
index ffcf6e5360..c198619400 100644
--- a/src/web/app/common/scripts/streaming/home.ts
+++ b/src/web/app/common/scripts/streaming/home.ts
@@ -16,7 +16,7 @@ export class HomeStream extends Stream {
 		// 最終利用日時を更新するため定期的にaliveメッセージを送信
 		setInterval(() => {
 			this.send({ type: 'alive' });
-			me.account.last_used_at = new Date();
+			me.account.lastUsedAt = new Date();
 		}, 1000 * 60);
 
 		// 自分の情報が更新されたとき
diff --git a/src/web/app/common/views/components/messaging-room.form.vue b/src/web/app/common/views/components/messaging-room.form.vue
index 01886b19c8..704f2016d8 100644
--- a/src/web/app/common/views/components/messaging-room.form.vue
+++ b/src/web/app/common/views/components/messaging-room.form.vue
@@ -151,9 +151,9 @@ export default Vue.extend({
 		send() {
 			this.sending = true;
 			(this as any).api('messaging/messages/create', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				text: this.text ? this.text : undefined,
-				file_id: this.file ? this.file.id : undefined
+				fileId: this.file ? this.file.id : undefined
 			}).then(message => {
 				this.clear();
 			}).catch(err => {
@@ -173,7 +173,7 @@ export default Vue.extend({
 			const data = JSON.parse(localStorage.getItem('message_drafts') || '{}');
 
 			data[this.draftId] = {
-				updated_at: new Date(),
+				updatedAt: new Date(),
 				data: {
 					text: this.text,
 					file: this.file
diff --git a/src/web/app/common/views/components/messaging-room.message.vue b/src/web/app/common/views/components/messaging-room.message.vue
index 5f2eb1ba86..d21cce1a0a 100644
--- a/src/web/app/common/views/components/messaging-room.message.vue
+++ b/src/web/app/common/views/components/messaging-room.message.vue
@@ -5,7 +5,7 @@
 	</router-link>
 	<div class="content">
 		<div class="balloon" :data-no-text="message.text == null">
-			<p class="read" v-if="isMe && message.is_read">%i18n:common.tags.mk-messaging-message.is-read%</p>
+			<p class="read" v-if="isMe && message.isRead">%i18n:common.tags.mk-messaging-message.is-read%</p>
 			<button class="delete-button" v-if="isMe" title="%i18n:common.delete%">
 				<img src="/assets/desktop/messaging/delete.png" alt="Delete"/>
 			</button>
@@ -25,7 +25,7 @@
 		<div></div>
 		<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
 		<footer>
-			<mk-time :time="message.created_at"/>
+			<mk-time :time="message.createdAt"/>
 			<template v-if="message.is_edited">%fa:pencil-alt%</template>
 		</footer>
 	</div>
@@ -43,7 +43,7 @@ export default Vue.extend({
 			return getAcct(this.message.user);
 		},
 		isMe(): boolean {
-			return this.message.user_id == (this as any).os.i.id;
+			return this.message.userId == (this as any).os.i.id;
 		},
 		urls(): string[] {
 			if (this.message.ast) {
diff --git a/src/web/app/common/views/components/messaging-room.vue b/src/web/app/common/views/components/messaging-room.vue
index 6ff808b617..36c53fd3fe 100644
--- a/src/web/app/common/views/components/messaging-room.vue
+++ b/src/web/app/common/views/components/messaging-room.vue
@@ -52,8 +52,8 @@ export default Vue.extend({
 	computed: {
 		_messages(): any[] {
 			return (this.messages as any).map(message => {
-				const date = new Date(message.created_at).getDate();
-				const month = new Date(message.created_at).getMonth() + 1;
+				const date = new Date(message.createdAt).getDate();
+				const month = new Date(message.createdAt).getMonth() + 1;
 				message._date = date;
 				message._datetext = `${month}月 ${date}日`;
 				return message;
@@ -123,7 +123,7 @@ export default Vue.extend({
 				const max = this.existMoreMessages ? 20 : 10;
 
 				(this as any).api('messaging/messages', {
-					user_id: this.user.id,
+					userId: this.user.id,
 					limit: max + 1,
 					until_id: this.existMoreMessages ? this.messages[0].id : undefined
 				}).then(messages => {
@@ -158,7 +158,7 @@ export default Vue.extend({
 			const isBottom = this.isBottom();
 
 			this.messages.push(message);
-			if (message.user_id != (this as any).os.i.id && !document.hidden) {
+			if (message.userId != (this as any).os.i.id && !document.hidden) {
 				this.connection.send({
 					type: 'read',
 					id: message.id
@@ -170,7 +170,7 @@ export default Vue.extend({
 				this.$nextTick(() => {
 					this.scrollToBottom();
 				});
-			} else if (message.user_id != (this as any).os.i.id) {
+			} else if (message.userId != (this as any).os.i.id) {
 				// Notify
 				this.notify('%i18n:common.tags.mk-messaging-room.new-message%');
 			}
@@ -181,7 +181,7 @@ export default Vue.extend({
 			ids.forEach(id => {
 				if (this.messages.some(x => x.id == id)) {
 					const exist = this.messages.map(x => x.id).indexOf(id);
-					this.messages[exist].is_read = true;
+					this.messages[exist].isRead = true;
 				}
 			});
 		},
@@ -223,7 +223,7 @@ export default Vue.extend({
 		onVisibilitychange() {
 			if (document.hidden) return;
 			this.messages.forEach(message => {
-				if (message.user_id !== (this as any).os.i.id && !message.is_read) {
+				if (message.userId !== (this as any).os.i.id && !message.isRead) {
 					this.connection.send({
 						type: 'read',
 						id: message.id
diff --git a/src/web/app/common/views/components/messaging.vue b/src/web/app/common/views/components/messaging.vue
index 88574b94d1..0272c67073 100644
--- a/src/web/app/common/views/components/messaging.vue
+++ b/src/web/app/common/views/components/messaging.vue
@@ -26,7 +26,7 @@
 				class="user"
 				:href="`/i/messaging/${getAcct(isMe(message) ? message.recipient : message.user)}`"
 				:data-is-me="isMe(message)"
-				:data-is-read="message.is_read"
+				:data-is-read="message.isRead"
 				@click.prevent="navigate(isMe(message) ? message.recipient : message.user)"
 				:key="message.id"
 			>
@@ -35,7 +35,7 @@
 					<header>
 						<span class="name">{{ isMe(message) ? message.recipient.name : message.user.name }}</span>
 						<span class="username">@{{ getAcct(isMe(message) ? message.recipient : message.user) }}</span>
-						<mk-time :time="message.created_at"/>
+						<mk-time :time="message.createdAt"/>
 					</header>
 					<div class="body">
 						<p class="text"><span class="me" v-if="isMe(message)">%i18n:common.tags.mk-messaging.you%:</span>{{ message.text }}</p>
@@ -95,19 +95,19 @@ export default Vue.extend({
 	methods: {
 		getAcct,
 		isMe(message) {
-			return message.user_id == (this as any).os.i.id;
+			return message.userId == (this as any).os.i.id;
 		},
 		onMessage(message) {
 			this.messages = this.messages.filter(m => !(
-				(m.recipient_id == message.recipient_id && m.user_id == message.user_id) ||
-				(m.recipient_id == message.user_id && m.user_id == message.recipient_id)));
+				(m.recipientId == message.recipientId && m.userId == message.userId) ||
+				(m.recipientId == message.userId && m.userId == message.recipientId)));
 
 			this.messages.unshift(message);
 		},
 		onRead(ids) {
 			ids.forEach(id => {
 				const found = this.messages.find(m => m.id == id);
-				if (found) found.is_read = true;
+				if (found) found.isRead = true;
 			});
 		},
 		search() {
diff --git a/src/web/app/common/views/components/othello.game.vue b/src/web/app/common/views/components/othello.game.vue
index 414d819a55..8150fe07f0 100644
--- a/src/web/app/common/views/components/othello.game.vue
+++ b/src/web/app/common/views/components/othello.game.vue
@@ -3,19 +3,19 @@
 	<header><b>{{ blackUser.name }}</b>(黒) vs <b>{{ whiteUser.name }}</b>(白)</header>
 
 	<div style="overflow: hidden">
-		<p class="turn" v-if="!iAmPlayer && !game.is_ended">{{ turnUser.name }}のターンです<mk-ellipsis/></p>
+		<p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ turnUser.name }}のターンです<mk-ellipsis/></p>
 		<p class="turn" v-if="logPos != logs.length">{{ turnUser.name }}のターン</p>
-		<p class="turn1" v-if="iAmPlayer && !game.is_ended && !isMyTurn">相手のターンです<mk-ellipsis/></p>
-		<p class="turn2" v-if="iAmPlayer && !game.is_ended && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">あなたのターンです</p>
-		<p class="result" v-if="game.is_ended && logPos == logs.length">
-			<template v-if="game.winner"><b>{{ game.winner.name }}</b>の勝ち{{ game.settings.is_llotheo ? ' (ロセオ)' : '' }}</template>
+		<p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">相手のターンです<mk-ellipsis/></p>
+		<p class="turn2" v-if="iAmPlayer && !game.isEnded && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">あなたのターンです</p>
+		<p class="result" v-if="game.isEnded && logPos == logs.length">
+			<template v-if="game.winner"><b>{{ game.winner.name }}</b>の勝ち{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template>
 			<template v-else>引き分け</template>
 		</p>
 	</div>
 
 	<div class="board" :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }">
 		<div v-for="(stone, i) in o.board"
-			:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.is_ended, myTurn: !game.is_ended && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
+			:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
 			@click="set(i)"
 			:title="'[' + (o.transformPosToXy(i)[0] + 1) + ', ' + (o.transformPosToXy(i)[1] + 1) + '] (' + i + ')'"
 		>
@@ -26,7 +26,7 @@
 
 	<p class="status"><b>{{ logPos }}ターン目</b> 黒:{{ o.blackCount }} 白:{{ o.whiteCount }} 合計:{{ o.blackCount + o.whiteCount }}</p>
 
-	<div class="player" v-if="game.is_ended">
+	<div class="player" v-if="game.isEnded">
 		<el-button-group>
 			<el-button type="primary" @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</el-button>
 			<el-button type="primary" @click="logPos--" :disabled="logPos == 0">%fa:angle-left%</el-button>
@@ -62,12 +62,12 @@ export default Vue.extend({
 	computed: {
 		iAmPlayer(): boolean {
 			if (!(this as any).os.isSignedIn) return false;
-			return this.game.user1_id == (this as any).os.i.id || this.game.user2_id == (this as any).os.i.id;
+			return this.game.user1Id == (this as any).os.i.id || this.game.user2Id == (this as any).os.i.id;
 		},
 		myColor(): Color {
 			if (!this.iAmPlayer) return null;
-			if (this.game.user1_id == (this as any).os.i.id && this.game.black == 1) return true;
-			if (this.game.user2_id == (this as any).os.i.id && this.game.black == 2) return true;
+			if (this.game.user1Id == (this as any).os.i.id && this.game.black == 1) return true;
+			if (this.game.user2Id == (this as any).os.i.id && this.game.black == 2) return true;
 			return false;
 		},
 		opColor(): Color {
@@ -97,11 +97,11 @@ export default Vue.extend({
 
 	watch: {
 		logPos(v) {
-			if (!this.game.is_ended) return;
+			if (!this.game.isEnded) return;
 			this.o = new Othello(this.game.settings.map, {
-				isLlotheo: this.game.settings.is_llotheo,
-				canPutEverywhere: this.game.settings.can_put_everywhere,
-				loopedBoard: this.game.settings.looped_board
+				isLlotheo: this.game.settings.isLlotheo,
+				canPutEverywhere: this.game.settings.canPutEverywhere,
+				loopedBoard: this.game.settings.loopedBoard
 			});
 			this.logs.forEach((log, i) => {
 				if (i < v) {
@@ -116,9 +116,9 @@ export default Vue.extend({
 		this.game = this.initGame;
 
 		this.o = new Othello(this.game.settings.map, {
-			isLlotheo: this.game.settings.is_llotheo,
-			canPutEverywhere: this.game.settings.can_put_everywhere,
-			loopedBoard: this.game.settings.looped_board
+			isLlotheo: this.game.settings.isLlotheo,
+			canPutEverywhere: this.game.settings.canPutEverywhere,
+			loopedBoard: this.game.settings.loopedBoard
 		});
 
 		this.game.logs.forEach(log => {
@@ -129,7 +129,7 @@ export default Vue.extend({
 		this.logPos = this.logs.length;
 
 		// 通信を取りこぼしてもいいように定期的にポーリングさせる
-		if (this.game.is_started && !this.game.is_ended) {
+		if (this.game.isStarted && !this.game.isEnded) {
 			this.pollingClock = setInterval(() => {
 				const crc32 = CRC32.str(this.logs.map(x => x.pos.toString()).join(''));
 				this.connection.send({
@@ -154,7 +154,7 @@ export default Vue.extend({
 
 	methods: {
 		set(pos) {
-			if (this.game.is_ended) return;
+			if (this.game.isEnded) return;
 			if (!this.iAmPlayer) return;
 			if (!this.isMyTurn) return;
 			if (!this.o.canPut(this.myColor, pos)) return;
@@ -194,16 +194,16 @@ export default Vue.extend({
 		},
 
 		checkEnd() {
-			this.game.is_ended = this.o.isEnded;
-			if (this.game.is_ended) {
+			this.game.isEnded = this.o.isEnded;
+			if (this.game.isEnded) {
 				if (this.o.winner === true) {
-					this.game.winner_id = this.game.black == 1 ? this.game.user1_id : this.game.user2_id;
+					this.game.winnerId = this.game.black == 1 ? this.game.user1Id : this.game.user2Id;
 					this.game.winner = this.game.black == 1 ? this.game.user1 : this.game.user2;
 				} else if (this.o.winner === false) {
-					this.game.winner_id = this.game.black == 1 ? this.game.user2_id : this.game.user1_id;
+					this.game.winnerId = this.game.black == 1 ? this.game.user2Id : this.game.user1Id;
 					this.game.winner = this.game.black == 1 ? this.game.user2 : this.game.user1;
 				} else {
-					this.game.winner_id = null;
+					this.game.winnerId = null;
 					this.game.winner = null;
 				}
 			}
@@ -214,9 +214,9 @@ export default Vue.extend({
 			this.game = game;
 
 			this.o = new Othello(this.game.settings.map, {
-				isLlotheo: this.game.settings.is_llotheo,
-				canPutEverywhere: this.game.settings.can_put_everywhere,
-				loopedBoard: this.game.settings.looped_board
+				isLlotheo: this.game.settings.isLlotheo,
+				canPutEverywhere: this.game.settings.canPutEverywhere,
+				loopedBoard: this.game.settings.loopedBoard
 			});
 
 			this.game.logs.forEach(log => {
diff --git a/src/web/app/common/views/components/othello.gameroom.vue b/src/web/app/common/views/components/othello.gameroom.vue
index 38a25f6686..dba9ccd16d 100644
--- a/src/web/app/common/views/components/othello.gameroom.vue
+++ b/src/web/app/common/views/components/othello.gameroom.vue
@@ -1,6 +1,6 @@
 <template>
 <div>
-	<x-room v-if="!g.is_started" :game="g" :connection="connection"/>
+	<x-room v-if="!g.isStarted" :game="g" :connection="connection"/>
 	<x-game v-else :init-game="g" :connection="connection"/>
 </div>
 </template>
diff --git a/src/web/app/common/views/components/othello.room.vue b/src/web/app/common/views/components/othello.room.vue
index 3965414836..a32be6b74f 100644
--- a/src/web/app/common/views/components/othello.room.vue
+++ b/src/web/app/common/views/components/othello.room.vue
@@ -41,9 +41,9 @@
 			<div slot="header">
 				<span>ルール</span>
 			</div>
-			<mk-switch v-model="game.settings.is_llotheo" @change="updateSettings" text="石の少ない方が勝ち(ロセオ)"/>
-			<mk-switch v-model="game.settings.looped_board" @change="updateSettings" text="ループマップ"/>
-			<mk-switch v-model="game.settings.can_put_everywhere" @change="updateSettings" text="どこでも置けるモード"/>
+			<mk-switch v-model="game.settings.isLlotheo" @change="updateSettings" text="石の少ない方が勝ち(ロセオ)"/>
+			<mk-switch v-model="game.settings.loopedBoard" @change="updateSettings" text="ループマップ"/>
+			<mk-switch v-model="game.settings.canPutEverywhere" @change="updateSettings" text="どこでも置けるモード"/>
 		</el-card>
 
 		<el-card class="bot-form" v-if="form">
@@ -116,13 +116,13 @@ export default Vue.extend({
 			return categories.filter((item, pos) => categories.indexOf(item) == pos);
 		},
 		isAccepted(): boolean {
-			if (this.game.user1_id == (this as any).os.i.id && this.game.user1_accepted) return true;
-			if (this.game.user2_id == (this as any).os.i.id && this.game.user2_accepted) return true;
+			if (this.game.user1Id == (this as any).os.i.id && this.game.user1Accepted) return true;
+			if (this.game.user2Id == (this as any).os.i.id && this.game.user2Accepted) return true;
 			return false;
 		},
 		isOpAccepted(): boolean {
-			if (this.game.user1_id != (this as any).os.i.id && this.game.user1_accepted) return true;
-			if (this.game.user2_id != (this as any).os.i.id && this.game.user2_accepted) return true;
+			if (this.game.user1Id != (this as any).os.i.id && this.game.user1Accepted) return true;
+			if (this.game.user2Id != (this as any).os.i.id && this.game.user2Accepted) return true;
 			return false;
 		}
 	},
@@ -133,8 +133,8 @@ export default Vue.extend({
 		this.connection.on('init-form', this.onInitForm);
 		this.connection.on('message', this.onMessage);
 
-		if (this.game.user1_id != (this as any).os.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
-		if (this.game.user2_id != (this as any).os.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
+		if (this.game.user1Id != (this as any).os.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
+		if (this.game.user2Id != (this as any).os.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
 	},
 
 	beforeDestroy() {
@@ -162,8 +162,8 @@ export default Vue.extend({
 		},
 
 		onChangeAccepts(accepts) {
-			this.game.user1_accepted = accepts.user1;
-			this.game.user2_accepted = accepts.user2;
+			this.game.user1Accepted = accepts.user1;
+			this.game.user2Accepted = accepts.user2;
 			this.$forceUpdate();
 		},
 
@@ -185,12 +185,12 @@ export default Vue.extend({
 		},
 
 		onInitForm(x) {
-			if (x.user_id == (this as any).os.i.id) return;
+			if (x.userId == (this as any).os.i.id) return;
 			this.form = x.form;
 		},
 
 		onMessage(x) {
-			if (x.user_id == (this as any).os.i.id) return;
+			if (x.userId == (this as any).os.i.id) return;
 			this.messages.unshift(x.message);
 		},
 
diff --git a/src/web/app/common/views/components/othello.vue b/src/web/app/common/views/components/othello.vue
index d650322341..7bdb471005 100644
--- a/src/web/app/common/views/components/othello.vue
+++ b/src/web/app/common/views/components/othello.vue
@@ -34,7 +34,7 @@
 				<img :src="`${i.parent.avatar_url}?thumbnail&size=32`" alt="">
 				<span class="name"><b>{{ i.parent.name }}</b></span>
 				<span class="username">@{{ i.parent.username }}</span>
-				<mk-time :time="i.created_at"/>
+				<mk-time :time="i.createdAt"/>
 			</div>
 		</section>
 		<section v-if="myGames.length > 0">
@@ -43,7 +43,7 @@
 				<img :src="`${g.user1.avatar_url}?thumbnail&size=32`" alt="">
 				<img :src="`${g.user2.avatar_url}?thumbnail&size=32`" alt="">
 				<span><b>{{ g.user1.name }}</b> vs <b>{{ g.user2.name }}</b></span>
-				<span class="state">{{ g.is_ended ? '終了' : '進行中' }}</span>
+				<span class="state">{{ g.isEnded ? '終了' : '進行中' }}</span>
 			</a>
 		</section>
 		<section v-if="games.length > 0">
@@ -52,7 +52,7 @@
 				<img :src="`${g.user1.avatar_url}?thumbnail&size=32`" alt="">
 				<img :src="`${g.user2.avatar_url}?thumbnail&size=32`" alt="">
 				<span><b>{{ g.user1.name }}</b> vs <b>{{ g.user2.name }}</b></span>
-				<span class="state">{{ g.is_ended ? '終了' : '進行中' }}</span>
+				<span class="state">{{ g.isEnded ? '終了' : '進行中' }}</span>
 			</a>
 		</section>
 	</div>
@@ -147,7 +147,7 @@ export default Vue.extend({
 					username
 				}).then(user => {
 					(this as any).api('othello/match', {
-						user_id: user.id
+						userId: user.id
 					}).then(res => {
 						if (res == null) {
 							this.matching = user;
@@ -164,7 +164,7 @@ export default Vue.extend({
 		},
 		accept(invitation) {
 			(this as any).api('othello/match', {
-				user_id: invitation.parent.id
+				userId: invitation.parent.id
 			}).then(game => {
 				if (game) {
 					this.matching = null;
diff --git a/src/web/app/common/views/components/poll.vue b/src/web/app/common/views/components/poll.vue
index 8156c8bc58..e46e89f55d 100644
--- a/src/web/app/common/views/components/poll.vue
+++ b/src/web/app/common/views/components/poll.vue
@@ -49,7 +49,7 @@ export default Vue.extend({
 		vote(id) {
 			if (this.poll.choices.some(c => c.is_voted)) return;
 			(this as any).api('posts/polls/vote', {
-				post_id: this.post.id,
+				postId: this.post.id,
 				choice: id
 			}).then(() => {
 				this.poll.choices.forEach(c => {
diff --git a/src/web/app/common/views/components/post-menu.vue b/src/web/app/common/views/components/post-menu.vue
index a53680e55a..35116db7e2 100644
--- a/src/web/app/common/views/components/post-menu.vue
+++ b/src/web/app/common/views/components/post-menu.vue
@@ -2,7 +2,7 @@
 <div class="mk-post-menu">
 	<div class="backdrop" ref="backdrop" @click="close"></div>
 	<div class="popover" :class="{ compact }" ref="popover">
-		<button v-if="post.user_id == os.i.id" @click="pin">%i18n:common.tags.mk-post-menu.pin%</button>
+		<button v-if="post.userId == os.i.id" @click="pin">%i18n:common.tags.mk-post-menu.pin%</button>
 	</div>
 </div>
 </template>
@@ -51,7 +51,7 @@ export default Vue.extend({
 	methods: {
 		pin() {
 			(this as any).api('i/pin', {
-				post_id: this.post.id
+				postId: this.post.id
 			}).then(() => {
 				this.$destroy();
 			});
diff --git a/src/web/app/common/views/components/reaction-picker.vue b/src/web/app/common/views/components/reaction-picker.vue
index df8100f2fc..bcb6b2b965 100644
--- a/src/web/app/common/views/components/reaction-picker.vue
+++ b/src/web/app/common/views/components/reaction-picker.vue
@@ -69,7 +69,7 @@ export default Vue.extend({
 	methods: {
 		react(reaction) {
 			(this as any).api('posts/reactions/create', {
-				post_id: this.post.id,
+				postId: this.post.id,
 				reaction: reaction
 			}).then(() => {
 				if (this.cb) this.cb();
diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue
index 273143262b..17154e6b31 100644
--- a/src/web/app/common/views/components/signin.vue
+++ b/src/web/app/common/views/components/signin.vue
@@ -6,7 +6,7 @@
 	<label class="password">
 		<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock%
 	</label>
-	<label class="token" v-if="user && user.account.two_factor_enabled">
+	<label class="token" v-if="user && user.account.twoFactorEnabled">
 		<input v-model="token" type="number" placeholder="%i18n:common.tags.mk-signin.token%" required/>%fa:lock%
 	</label>
 	<button type="submit" :disabled="signing">{{ signing ? '%i18n:common.tags.mk-signin.signing-in%' : '%i18n:common.tags.mk-signin.signin%' }}</button>
@@ -43,7 +43,7 @@ export default Vue.extend({
 			(this as any).api('signin', {
 				username: this.username,
 				password: this.password,
-				token: this.user && this.user.account.two_factor_enabled ? this.token : undefined
+				token: this.user && this.user.account.twoFactorEnabled ? this.token : undefined
 			}).then(() => {
 				location.reload();
 			}).catch(() => {
diff --git a/src/web/app/common/views/components/twitter-setting.vue b/src/web/app/common/views/components/twitter-setting.vue
index 15968d20a6..082d2b435d 100644
--- a/src/web/app/common/views/components/twitter-setting.vue
+++ b/src/web/app/common/views/components/twitter-setting.vue
@@ -1,13 +1,13 @@
 <template>
 <div class="mk-twitter-setting">
 	<p>%i18n:common.tags.mk-twitter-setting.description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:common.tags.mk-twitter-setting.detail%</a></p>
-	<p class="account" v-if="os.i.account.twitter" :title="`Twitter ID: ${os.i.account.twitter.user_id}`">%i18n:common.tags.mk-twitter-setting.connected-to%: <a :href="`https://twitter.com/${os.i.account.twitter.screen_name}`" target="_blank">@{{ os.i.account.twitter.screen_name }}</a></p>
+	<p class="account" v-if="os.i.account.twitter" :title="`Twitter ID: ${os.i.account.twitter.userId}`">%i18n:common.tags.mk-twitter-setting.connected-to%: <a :href="`https://twitter.com/${os.i.account.twitter.screenName}`" target="_blank">@{{ os.i.account.twitter.screenName }}</a></p>
 	<p>
 		<a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.account.twitter ? '%i18n:common.tags.mk-twitter-setting.reconnect%' : '%i18n:common.tags.mk-twitter-setting.connect%' }}</a>
 		<span v-if="os.i.account.twitter"> or </span>
 		<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.account.twitter" @click.prevent="disconnect">%i18n:common.tags.mk-twitter-setting.disconnect%</a>
 	</p>
-	<p class="id" v-if="os.i.account.twitter">Twitter ID: {{ os.i.account.twitter.user_id }}</p>
+	<p class="id" v-if="os.i.account.twitter">Twitter ID: {{ os.i.account.twitter.userId }}</p>
 </div>
 </template>
 
diff --git a/src/web/app/common/views/components/uploader.vue b/src/web/app/common/views/components/uploader.vue
index 73006b16e9..c74a1edb41 100644
--- a/src/web/app/common/views/components/uploader.vue
+++ b/src/web/app/common/views/components/uploader.vue
@@ -53,7 +53,7 @@ export default Vue.extend({
 			data.append('i', (this as any).os.i.account.token);
 			data.append('file', file);
 
-			if (folder) data.append('folder_id', folder);
+			if (folder) data.append('folderId', folder);
 
 			const xhr = new XMLHttpRequest();
 			xhr.open('POST', apiUrl + '/drive/files/create', true);
diff --git a/src/web/app/common/views/components/welcome-timeline.vue b/src/web/app/common/views/components/welcome-timeline.vue
index 7586e9264e..c61cae0f76 100644
--- a/src/web/app/common/views/components/welcome-timeline.vue
+++ b/src/web/app/common/views/components/welcome-timeline.vue
@@ -10,7 +10,7 @@
 				<span class="username">@{{ getAcct(post.user) }}</span>
 				<div class="info">
 					<router-link class="created-at" :to="`/@${getAcct(post.user)}/${post.id}`">
-						<mk-time :time="post.created_at"/>
+						<mk-time :time="post.createdAt"/>
 					</router-link>
 				</div>
 			</header>
diff --git a/src/web/app/common/views/widgets/slideshow.vue b/src/web/app/common/views/widgets/slideshow.vue
index e9451663e2..ad32299f37 100644
--- a/src/web/app/common/views/widgets/slideshow.vue
+++ b/src/web/app/common/views/widgets/slideshow.vue
@@ -97,7 +97,7 @@ export default define({
 			this.fetching = true;
 
 			(this as any).api('drive/files', {
-				folder_id: this.props.folder,
+				folderId: this.props.folder,
 				type: 'image/*',
 				limit: 100
 			}).then(images => {
diff --git a/src/web/app/desktop/api/update-avatar.ts b/src/web/app/desktop/api/update-avatar.ts
index 8f748d853c..445ef7d745 100644
--- a/src/web/app/desktop/api/update-avatar.ts
+++ b/src/web/app/desktop/api/update-avatar.ts
@@ -49,7 +49,7 @@ export default (os: OS) => (cb, file = null) => {
 		}).$mount();
 		document.body.appendChild(dialog.$el);
 
-		if (folder) data.append('folder_id', folder.id);
+		if (folder) data.append('folderId', folder.id);
 
 		const xhr = new XMLHttpRequest();
 		xhr.open('POST', apiUrl + '/drive/files/create', true);
@@ -68,9 +68,9 @@ export default (os: OS) => (cb, file = null) => {
 
 	const set = file => {
 		os.api('i/update', {
-			avatar_id: file.id
+			avatarId: file.id
 		}).then(i => {
-			os.i.avatar_id = i.avatar_id;
+			os.i.avatarId = i.avatarId;
 			os.i.avatar_url = i.avatar_url;
 
 			os.apis.dialog({
diff --git a/src/web/app/desktop/api/update-banner.ts b/src/web/app/desktop/api/update-banner.ts
index 9ed48b2670..002efce8ce 100644
--- a/src/web/app/desktop/api/update-banner.ts
+++ b/src/web/app/desktop/api/update-banner.ts
@@ -49,7 +49,7 @@ export default (os: OS) => (cb, file = null) => {
 		}).$mount();
 		document.body.appendChild(dialog.$el);
 
-		if (folder) data.append('folder_id', folder.id);
+		if (folder) data.append('folderId', folder.id);
 
 		const xhr = new XMLHttpRequest();
 		xhr.open('POST', apiUrl + '/drive/files/create', true);
@@ -68,9 +68,9 @@ export default (os: OS) => (cb, file = null) => {
 
 	const set = file => {
 		os.api('i/update', {
-			banner_id: file.id
+			bannerId: file.id
 		}).then(i => {
-			os.i.banner_id = i.banner_id;
+			os.i.bannerId = i.bannerId;
 			os.i.banner_url = i.banner_url;
 
 			os.apis.dialog({
diff --git a/src/web/app/desktop/views/components/activity.vue b/src/web/app/desktop/views/components/activity.vue
index 33b53eb700..480b956ecc 100644
--- a/src/web/app/desktop/views/components/activity.vue
+++ b/src/web/app/desktop/views/components/activity.vue
@@ -43,7 +43,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('aggregation/users/activity', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			limit: 20 * 7
 		}).then(activity => {
 			this.activity = activity;
diff --git a/src/web/app/desktop/views/components/drive.file.vue b/src/web/app/desktop/views/components/drive.file.vue
index 924ff7052d..85f8361c9f 100644
--- a/src/web/app/desktop/views/components/drive.file.vue
+++ b/src/web/app/desktop/views/components/drive.file.vue
@@ -9,10 +9,10 @@
 	@contextmenu.prevent.stop="onContextmenu"
 	:title="title"
 >
-	<div class="label" v-if="os.i.avatar_id == file.id"><img src="/assets/label.svg"/>
+	<div class="label" v-if="os.i.avatarId == file.id"><img src="/assets/label.svg"/>
 		<p>%i18n:desktop.tags.mk-drive-browser-file.avatar%</p>
 	</div>
-	<div class="label" v-if="os.i.banner_id == file.id"><img src="/assets/label.svg"/>
+	<div class="label" v-if="os.i.bannerId == file.id"><img src="/assets/label.svg"/>
 		<p>%i18n:desktop.tags.mk-drive-browser-file.banner%</p>
 	</div>
 	<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
@@ -50,8 +50,8 @@ export default Vue.extend({
 			return `${this.file.name}\n${this.file.type} ${Vue.filter('bytes')(this.file.datasize)}`;
 		},
 		background(): string {
-			return this.file.properties.average_color
-				? `rgb(${this.file.properties.average_color.join(',')})`
+			return this.file.properties.avgColor
+				? `rgb(${this.file.properties.avgColor.join(',')})`
 				: 'transparent';
 		}
 	},
@@ -129,10 +129,10 @@ export default Vue.extend({
 		},
 
 		onThumbnailLoaded() {
-			if (this.file.properties.average_color) {
+			if (this.file.properties.avgColor) {
 				anime({
 					targets: this.$refs.thumbnail,
-					backgroundColor: `rgba(${this.file.properties.average_color.join(',')}, 0)`,
+					backgroundColor: `rgba(${this.file.properties.avgColor.join(',')}, 0)`,
 					duration: 100,
 					easing: 'linear'
 				});
@@ -147,7 +147,7 @@ export default Vue.extend({
 				allowEmpty: false
 			}).then(name => {
 				(this as any).api('drive/files/update', {
-					file_id: this.file.id,
+					fileId: this.file.id,
 					name: name
 				})
 			});
diff --git a/src/web/app/desktop/views/components/drive.folder.vue b/src/web/app/desktop/views/components/drive.folder.vue
index a8a9a01370..a926bf47b2 100644
--- a/src/web/app/desktop/views/components/drive.folder.vue
+++ b/src/web/app/desktop/views/components/drive.folder.vue
@@ -135,8 +135,8 @@ export default Vue.extend({
 				const file = JSON.parse(driveFile);
 				this.browser.removeFile(file.id);
 				(this as any).api('drive/files/update', {
-					file_id: file.id,
-					folder_id: this.folder.id
+					fileId: file.id,
+					folderId: this.folder.id
 				});
 			}
 			//#endregion
@@ -151,8 +151,8 @@ export default Vue.extend({
 
 				this.browser.removeFolder(folder.id);
 				(this as any).api('drive/folders/update', {
-					folder_id: folder.id,
-					parent_id: this.folder.id
+					folderId: folder.id,
+					parentId: this.folder.id
 				}).then(() => {
 					// noop
 				}).catch(err => {
@@ -204,7 +204,7 @@ export default Vue.extend({
 				default: this.folder.name
 			}).then(name => {
 				(this as any).api('drive/folders/update', {
-					folder_id: this.folder.id,
+					folderId: this.folder.id,
 					name: name
 				});
 			});
diff --git a/src/web/app/desktop/views/components/drive.nav-folder.vue b/src/web/app/desktop/views/components/drive.nav-folder.vue
index dfbf116bff..d885a72f7f 100644
--- a/src/web/app/desktop/views/components/drive.nav-folder.vue
+++ b/src/web/app/desktop/views/components/drive.nav-folder.vue
@@ -78,8 +78,8 @@ export default Vue.extend({
 				const file = JSON.parse(driveFile);
 				this.browser.removeFile(file.id);
 				(this as any).api('drive/files/update', {
-					file_id: file.id,
-					folder_id: this.folder ? this.folder.id : null
+					fileId: file.id,
+					folderId: this.folder ? this.folder.id : null
 				});
 			}
 			//#endregion
@@ -92,8 +92,8 @@ export default Vue.extend({
 				if (this.folder && folder.id == this.folder.id) return;
 				this.browser.removeFolder(folder.id);
 				(this as any).api('drive/folders/update', {
-					folder_id: folder.id,
-					parent_id: this.folder ? this.folder.id : null
+					folderId: folder.id,
+					parentId: this.folder ? this.folder.id : null
 				});
 			}
 			//#endregion
diff --git a/src/web/app/desktop/views/components/drive.vue b/src/web/app/desktop/views/components/drive.vue
index 0fafa8cf23..c766dfec12 100644
--- a/src/web/app/desktop/views/components/drive.vue
+++ b/src/web/app/desktop/views/components/drive.vue
@@ -160,7 +160,7 @@ export default Vue.extend({
 
 		onStreamDriveFileUpdated(file) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != file.folder_id) {
+			if (current != file.folderId) {
 				this.removeFile(file);
 			} else {
 				this.addFile(file, true);
@@ -173,7 +173,7 @@ export default Vue.extend({
 
 		onStreamDriveFolderUpdated(folder) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != folder.parent_id) {
+			if (current != folder.parentId) {
 				this.removeFolder(folder);
 			} else {
 				this.addFolder(folder, true);
@@ -282,8 +282,8 @@ export default Vue.extend({
 				if (this.files.some(f => f.id == file.id)) return;
 				this.removeFile(file.id);
 				(this as any).api('drive/files/update', {
-					file_id: file.id,
-					folder_id: this.folder ? this.folder.id : null
+					fileId: file.id,
+					folderId: this.folder ? this.folder.id : null
 				});
 			}
 			//#endregion
@@ -298,8 +298,8 @@ export default Vue.extend({
 				if (this.folders.some(f => f.id == folder.id)) return false;
 				this.removeFolder(folder.id);
 				(this as any).api('drive/folders/update', {
-					folder_id: folder.id,
-					parent_id: this.folder ? this.folder.id : null
+					folderId: folder.id,
+					parentId: this.folder ? this.folder.id : null
 				}).then(() => {
 					// noop
 				}).catch(err => {
@@ -332,7 +332,7 @@ export default Vue.extend({
 			}).then(url => {
 				(this as any).api('drive/files/upload_from_url', {
 					url: url,
-					folder_id: this.folder ? this.folder.id : undefined
+					folderId: this.folder ? this.folder.id : undefined
 				});
 
 				(this as any).apis.dialog({
@@ -352,7 +352,7 @@ export default Vue.extend({
 			}).then(name => {
 				(this as any).api('drive/folders/create', {
 					name: name,
-					folder_id: this.folder ? this.folder.id : undefined
+					folderId: this.folder ? this.folder.id : undefined
 				}).then(folder => {
 					this.addFolder(folder, true);
 				});
@@ -412,7 +412,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('drive/folders/show', {
-				folder_id: target
+				folderId: target
 			}).then(folder => {
 				this.folder = folder;
 				this.hierarchyFolders = [];
@@ -431,7 +431,7 @@ export default Vue.extend({
 
 		addFolder(folder, unshift = false) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != folder.parent_id) return;
+			if (current != folder.parentId) return;
 
 			if (this.folders.some(f => f.id == folder.id)) {
 				const exist = this.folders.map(f => f.id).indexOf(folder.id);
@@ -448,7 +448,7 @@ export default Vue.extend({
 
 		addFile(file, unshift = false) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != file.folder_id) return;
+			if (current != file.folderId) return;
 
 			if (this.files.some(f => f.id == file.id)) {
 				const exist = this.files.map(f => f.id).indexOf(file.id);
@@ -514,7 +514,7 @@ export default Vue.extend({
 
 			// フォルダ一覧取得
 			(this as any).api('drive/folders', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: foldersMax + 1
 			}).then(folders => {
 				if (folders.length == foldersMax + 1) {
@@ -527,7 +527,7 @@ export default Vue.extend({
 
 			// ファイル一覧取得
 			(this as any).api('drive/files', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: filesMax + 1
 			}).then(files => {
 				if (files.length == filesMax + 1) {
@@ -557,7 +557,7 @@ export default Vue.extend({
 
 			// ファイル一覧取得
 			(this as any).api('drive/files', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: max + 1
 			}).then(files => {
 				if (files.length == max + 1) {
diff --git a/src/web/app/desktop/views/components/follow-button.vue b/src/web/app/desktop/views/components/follow-button.vue
index fc4f871888..01b7e2aefd 100644
--- a/src/web/app/desktop/views/components/follow-button.vue
+++ b/src/web/app/desktop/views/components/follow-button.vue
@@ -67,7 +67,7 @@ export default Vue.extend({
 			this.wait = true;
 			if (this.user.is_following) {
 				(this as any).api('following/delete', {
-					user_id: this.user.id
+					userId: this.user.id
 				}).then(() => {
 					this.user.is_following = false;
 				}).catch(err => {
@@ -77,7 +77,7 @@ export default Vue.extend({
 				});
 			} else {
 				(this as any).api('following/create', {
-					user_id: this.user.id
+					userId: this.user.id
 				}).then(() => {
 					this.user.is_following = true;
 				}).catch(err => {
diff --git a/src/web/app/desktop/views/components/followers.vue b/src/web/app/desktop/views/components/followers.vue
index 4541a00072..e8330289ca 100644
--- a/src/web/app/desktop/views/components/followers.vue
+++ b/src/web/app/desktop/views/components/followers.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-users-list
 	:fetch="fetch"
-	:count="user.followers_count"
+	:count="user.followersCount"
 	:you-know-count="user.followers_you_know_count"
 >
 	フォロワーはいないようです。
@@ -15,7 +15,7 @@ export default Vue.extend({
 	methods: {
 		fetch(iknow, limit, cursor, cb) {
 			(this as any).api('users/followers', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				iknow: iknow,
 				limit: limit,
 				cursor: cursor ? cursor : undefined
diff --git a/src/web/app/desktop/views/components/following.vue b/src/web/app/desktop/views/components/following.vue
index e0b9f11695..0dab6ac7b3 100644
--- a/src/web/app/desktop/views/components/following.vue
+++ b/src/web/app/desktop/views/components/following.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-users-list
 	:fetch="fetch"
-	:count="user.following_count"
+	:count="user.followingCount"
 	:you-know-count="user.following_you_know_count"
 >
 	フォロー中のユーザーはいないようです。
@@ -15,7 +15,7 @@ export default Vue.extend({
 	methods: {
 		fetch(iknow, limit, cursor, cb) {
 			(this as any).api('users/following', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				iknow: iknow,
 				limit: limit,
 				cursor: cursor ? cursor : undefined
diff --git a/src/web/app/desktop/views/components/home.vue b/src/web/app/desktop/views/components/home.vue
index a4ce1ef94b..7145ddce03 100644
--- a/src/web/app/desktop/views/components/home.vue
+++ b/src/web/app/desktop/views/components/home.vue
@@ -53,7 +53,7 @@
 			<div class="main">
 				<a @click="hint">カスタマイズのヒント</a>
 				<div>
-					<mk-post-form v-if="os.i.account.client_settings.showPostFormOnTopOfTl"/>
+					<mk-post-form v-if="os.i.account.clientSettings.showPostFormOnTopOfTl"/>
 					<mk-timeline ref="tl" @loaded="onTlLoaded"/>
 				</div>
 			</div>
@@ -63,7 +63,7 @@
 				<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
 			</div>
 			<div class="main">
-				<mk-post-form v-if="os.i.account.client_settings.showPostFormOnTopOfTl"/>
+				<mk-post-form v-if="os.i.account.clientSettings.showPostFormOnTopOfTl"/>
 				<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
 				<mk-mentions @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
 			</div>
@@ -104,16 +104,16 @@ export default Vue.extend({
 		home: {
 			get(): any[] {
 				//#region 互換性のため
-				(this as any).os.i.account.client_settings.home.forEach(w => {
+				(this as any).os.i.account.clientSettings.home.forEach(w => {
 					if (w.name == 'rss-reader') w.name = 'rss';
 					if (w.name == 'user-recommendation') w.name = 'users';
 					if (w.name == 'recommended-polls') w.name = 'polls';
 				});
 				//#endregion
-				return (this as any).os.i.account.client_settings.home;
+				return (this as any).os.i.account.clientSettings.home;
 			},
 			set(value) {
-				(this as any).os.i.account.client_settings.home = value;
+				(this as any).os.i.account.clientSettings.home = value;
 			}
 		},
 		left(): any[] {
@@ -126,7 +126,7 @@ export default Vue.extend({
 	created() {
 		this.widgets.left = this.left;
 		this.widgets.right = this.right;
-		this.$watch('os.i.account.client_settings', i => {
+		this.$watch('os.i.account.clientSettings', i => {
 			this.widgets.left = this.left;
 			this.widgets.right = this.right;
 		}, {
@@ -161,17 +161,17 @@ export default Vue.extend({
 		},
 		onHomeUpdated(data) {
 			if (data.home) {
-				(this as any).os.i.account.client_settings.home = data.home;
+				(this as any).os.i.account.clientSettings.home = data.home;
 				this.widgets.left = data.home.filter(w => w.place == 'left');
 				this.widgets.right = data.home.filter(w => w.place == 'right');
 			} else {
-				const w = (this as any).os.i.account.client_settings.home.find(w => w.id == data.id);
+				const w = (this as any).os.i.account.clientSettings.home.find(w => w.id == data.id);
 				if (w != null) {
 					w.data = data.data;
 					this.$refs[w.id][0].preventSave = true;
 					this.$refs[w.id][0].props = w.data;
-					this.widgets.left = (this as any).os.i.account.client_settings.home.filter(w => w.place == 'left');
-					this.widgets.right = (this as any).os.i.account.client_settings.home.filter(w => w.place == 'right');
+					this.widgets.left = (this as any).os.i.account.clientSettings.home.filter(w => w.place == 'left');
+					this.widgets.right = (this as any).os.i.account.clientSettings.home.filter(w => w.place == 'right');
 				}
 			}
 		},
diff --git a/src/web/app/desktop/views/components/media-image.vue b/src/web/app/desktop/views/components/media-image.vue
index bc02d0f9be..51309a0578 100644
--- a/src/web/app/desktop/views/components/media-image.vue
+++ b/src/web/app/desktop/views/components/media-image.vue
@@ -18,7 +18,7 @@ export default Vue.extend({
 	computed: {
 		style(): any {
 			return {
-				'background-color': this.image.properties.average_color ? `rgb(${this.image.properties.average_color.join(',')})` : 'transparent',
+				'background-color': this.image.properties.avgColor ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
 				'background-image': `url(${this.image.url}?thumbnail&size=512)`
 			};
 		}
diff --git a/src/web/app/desktop/views/components/notifications.vue b/src/web/app/desktop/views/components/notifications.vue
index b48ffc1746..62593cf97e 100644
--- a/src/web/app/desktop/views/components/notifications.vue
+++ b/src/web/app/desktop/views/components/notifications.vue
@@ -3,7 +3,7 @@
 	<div class="notifications" v-if="notifications.length != 0">
 		<template v-for="(notification, i) in _notifications">
 			<div class="notification" :class="notification.type" :key="notification.id">
-				<mk-time :time="notification.created_at"/>
+				<mk-time :time="notification.createdAt"/>
 				<template v-if="notification.type == 'reaction'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.user)}`" v-user-preview="notification.user.id">
 						<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
@@ -19,12 +19,12 @@
 					</div>
 				</template>
 				<template v-if="notification.type == 'repost'">
-					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">
+					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
 						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:retweet%
-							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">{{ notification.post.user.name }}</router-link>
+							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">{{ notification.post.user.name }}</router-link>
 						</p>
 						<router-link class="post-ref" :to="`/@${getAcct(notification.post.user)}/${notification.post.id}`">
 							%fa:quote-left%{{ getPostSummary(notification.post.repost) }}%fa:quote-right%
@@ -32,12 +32,12 @@
 					</div>
 				</template>
 				<template v-if="notification.type == 'quote'">
-					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">
+					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
 						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:quote-left%
-							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">{{ notification.post.user.name }}</router-link>
+							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">{{ notification.post.user.name }}</router-link>
 						</p>
 						<router-link class="post-preview" :to="`/@${getAcct(notification.post.user)}/${notification.post.id}`">{{ getPostSummary(notification.post) }}</router-link>
 					</div>
@@ -53,23 +53,23 @@
 					</div>
 				</template>
 				<template v-if="notification.type == 'reply'">
-					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">
+					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
 						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:reply%
-							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">{{ notification.post.user.name }}</router-link>
+							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">{{ notification.post.user.name }}</router-link>
 						</p>
 						<router-link class="post-preview" :to="`/@${getAcct(notification.post.user)}/${notification.post.id}`">{{ getPostSummary(notification.post) }}</router-link>
 					</div>
 				</template>
 				<template v-if="notification.type == 'mention'">
-					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">
+					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
 						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:at%
-							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.user_id">{{ notification.post.user.name }}</router-link>
+							<router-link :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">{{ notification.post.user.name }}</router-link>
 						</p>
 						<a class="post-preview" :href="`/@${getAcct(notification.post.user)}/${notification.post.id}`">{{ getPostSummary(notification.post) }}</a>
 					</div>
@@ -120,8 +120,8 @@ export default Vue.extend({
 	computed: {
 		_notifications(): any[] {
 			return (this.notifications as any).map(notification => {
-				const date = new Date(notification.created_at).getDate();
-				const month = new Date(notification.created_at).getMonth() + 1;
+				const date = new Date(notification.createdAt).getDate();
+				const month = new Date(notification.createdAt).getMonth() + 1;
 				notification._date = date;
 				notification._datetext = `${month}月 ${date}日`;
 				return notification;
diff --git a/src/web/app/desktop/views/components/post-detail.sub.vue b/src/web/app/desktop/views/components/post-detail.sub.vue
index 59d8db04ce..7453a8bfcf 100644
--- a/src/web/app/desktop/views/components/post-detail.sub.vue
+++ b/src/web/app/desktop/views/components/post-detail.sub.vue
@@ -1,17 +1,17 @@
 <template>
 <div class="sub" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.user_id"/>
+		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
 			<div class="left">
-				<router-link class="name" :to="`/@${acct}`" v-user-preview="post.user_id">{{ post.user.name }}</router-link>
+				<router-link class="name" :to="`/@${acct}`" v-user-preview="post.userId">{{ post.user.name }}</router-link>
 				<span class="username">@{{ acct }}</span>
 			</div>
 			<div class="right">
 				<router-link class="time" :to="`/@${acct}/${post.id}`">
-					<mk-time :time="post.created_at"/>
+					<mk-time :time="post.createdAt"/>
 				</router-link>
 			</div>
 		</header>
@@ -37,7 +37,7 @@ export default Vue.extend({
 			return getAcct(this.post.user);
 		},
 		title(): string {
-			return dateStringify(this.post.created_at);
+			return dateStringify(this.post.createdAt);
 		}
 	}
 });
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index f09bf4cbd5..1ab751aaf8 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -2,7 +2,7 @@
 <div class="mk-post-detail" :title="title">
 	<button
 		class="read-more"
-		v-if="p.reply && p.reply.reply_id && context == null"
+		v-if="p.reply && p.reply.replyId && context == null"
 		title="会話をもっと読み込む"
 		@click="fetchContext"
 		:disabled="contextFetching"
@@ -18,7 +18,7 @@
 	</div>
 	<div class="repost" v-if="isRepost">
 		<p>
-			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.user_id">
+			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.userId">
 				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=32`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
@@ -34,7 +34,7 @@
 			<router-link class="name" :to="`/@${acct}`" v-user-preview="p.user.id">{{ p.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="time" :to="`/@${acct}/${p.id}`">
-				<mk-time :time="p.created_at"/>
+				<mk-time :time="p.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
@@ -115,7 +115,7 @@ export default Vue.extend({
 		isRepost(): boolean {
 			return (this.post.repost &&
 				this.post.text == null &&
-				this.post.media_ids == null &&
+				this.post.mediaIds == null &&
 				this.post.poll == null);
 		},
 		p(): any {
@@ -129,7 +129,7 @@ export default Vue.extend({
 				: 0;
 		},
 		title(): string {
-			return dateStringify(this.p.created_at);
+			return dateStringify(this.p.createdAt);
 		},
 		urls(): string[] {
 			if (this.p.ast) {
@@ -145,7 +145,7 @@ export default Vue.extend({
 		// Get replies
 		if (!this.compact) {
 			(this as any).api('posts/replies', {
-				post_id: this.p.id,
+				postId: this.p.id,
 				limit: 8
 			}).then(replies => {
 				this.replies = replies;
@@ -154,7 +154,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.clientSettings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
@@ -176,7 +176,7 @@ export default Vue.extend({
 
 			// Fetch context
 			(this as any).api('posts/context', {
-				post_id: this.p.reply_id
+				postId: this.p.replyId
 			}).then(context => {
 				this.contextFetching = false;
 				this.context = context.reverse();
diff --git a/src/web/app/desktop/views/components/post-form.vue b/src/web/app/desktop/views/components/post-form.vue
index 78f6d445af..11028ceb52 100644
--- a/src/web/app/desktop/views/components/post-form.vue
+++ b/src/web/app/desktop/views/components/post-form.vue
@@ -219,9 +219,9 @@ export default Vue.extend({
 
 			(this as any).api('posts/create', {
 				text: this.text == '' ? undefined : this.text,
-				media_ids: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
-				reply_id: this.reply ? this.reply.id : undefined,
-				repost_id: this.repost ? this.repost.id : undefined,
+				mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
+				replyId: this.reply ? this.reply.id : undefined,
+				repostId: this.repost ? this.repost.id : undefined,
 				poll: this.poll ? (this.$refs.poll as any).get() : undefined,
 				geo: this.geo ? {
 					latitude: this.geo.latitude,
@@ -255,7 +255,7 @@ export default Vue.extend({
 			const data = JSON.parse(localStorage.getItem('drafts') || '{}');
 
 			data[this.draftId] = {
-				updated_at: new Date(),
+				updatedAt: new Date(),
 				data: {
 					text: this.text,
 					files: this.files,
diff --git a/src/web/app/desktop/views/components/post-preview.vue b/src/web/app/desktop/views/components/post-preview.vue
index 808220c0e0..450632656d 100644
--- a/src/web/app/desktop/views/components/post-preview.vue
+++ b/src/web/app/desktop/views/components/post-preview.vue
@@ -1,14 +1,14 @@
 <template>
 <div class="mk-post-preview" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.user_id"/>
+		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
-			<router-link class="name" :to="`/@${acct}`" v-user-preview="post.user_id">{{ post.user.name }}</router-link>
+			<router-link class="name" :to="`/@${acct}`" v-user-preview="post.userId">{{ post.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="time" :to="`/@${acct}/${post.id}`">
-				<mk-time :time="post.created_at"/>
+				<mk-time :time="post.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
@@ -30,7 +30,7 @@ export default Vue.extend({
 			return getAcct(this.post.user);
 		},
 		title(): string {
-			return dateStringify(this.post.created_at);
+			return dateStringify(this.post.createdAt);
 		}
 	}
 });
diff --git a/src/web/app/desktop/views/components/posts.post.sub.vue b/src/web/app/desktop/views/components/posts.post.sub.vue
index 120700877c..7d2695d6b9 100644
--- a/src/web/app/desktop/views/components/posts.post.sub.vue
+++ b/src/web/app/desktop/views/components/posts.post.sub.vue
@@ -1,14 +1,14 @@
 <template>
 <div class="sub" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.user_id"/>
+		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
-			<router-link class="name" :to="`/@${acct}`" v-user-preview="post.user_id">{{ post.user.name }}</router-link>
+			<router-link class="name" :to="`/@${acct}`" v-user-preview="post.userId">{{ post.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="created-at" :to="`/@${acct}/${post.id}`">
-				<mk-time :time="post.created_at"/>
+				<mk-time :time="post.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
@@ -30,7 +30,7 @@ export default Vue.extend({
 			return getAcct(this.post.user);
 		},
 		title(): string {
-			return dateStringify(this.post.created_at);
+			return dateStringify(this.post.createdAt);
 		}
 	}
 });
diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue
index 6b4d3d2789..185a621aae 100644
--- a/src/web/app/desktop/views/components/posts.post.vue
+++ b/src/web/app/desktop/views/components/posts.post.vue
@@ -5,15 +5,15 @@
 	</div>
 	<div class="repost" v-if="isRepost">
 		<p>
-			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.user_id">
+			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.userId">
 				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=32`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
 			<span>{{ '%i18n:desktop.tags.mk-timeline-post.reposted-by%'.substr(0, '%i18n:desktop.tags.mk-timeline-post.reposted-by%'.indexOf('{')) }}</span>
-			<a class="name" :href="`/@${acct}`" v-user-preview="post.user_id">{{ post.user.name }}</a>
+			<a class="name" :href="`/@${acct}`" v-user-preview="post.userId">{{ post.user.name }}</a>
 			<span>{{ '%i18n:desktop.tags.mk-timeline-post.reposted-by%'.substr('%i18n:desktop.tags.mk-timeline-post.reposted-by%'.indexOf('}') + 1) }}</span>
 		</p>
-		<mk-time :time="post.created_at"/>
+		<mk-time :time="post.createdAt"/>
 	</div>
 	<article>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
@@ -22,13 +22,13 @@
 		<div class="main">
 			<header>
 				<router-link class="name" :to="`/@${acct}`" v-user-preview="p.user.id">{{ acct }}</router-link>
-				<span class="is-bot" v-if="p.user.host === null && p.user.account.is_bot">bot</span>
+				<span class="is-bot" v-if="p.user.host === null && p.user.account.isBot">bot</span>
 				<span class="username">@{{ acct }}</span>
 				<div class="info">
 					<span class="app" v-if="p.app">via <b>{{ p.app.name }}</b></span>
-					<span class="mobile" v-if="p.via_mobile">%fa:mobile-alt%</span>
+					<span class="mobile" v-if="p.viaMobile">%fa:mobile-alt%</span>
 					<router-link class="created-at" :to="url">
-						<mk-time :time="p.created_at"/>
+						<mk-time :time="p.createdAt"/>
 					</router-link>
 				</div>
 			</header>
@@ -122,7 +122,7 @@ export default Vue.extend({
 		isRepost(): boolean {
 			return (this.post.repost &&
 				this.post.text == null &&
-				this.post.media_ids == null &&
+				this.post.mediaIds == null &&
 				this.post.poll == null);
 		},
 		p(): any {
@@ -136,7 +136,7 @@ export default Vue.extend({
 				: 0;
 		},
 		title(): string {
-			return dateStringify(this.p.created_at);
+			return dateStringify(this.p.createdAt);
 		},
 		url(): string {
 			return `/@${this.acct}/${this.p.id}`;
@@ -166,7 +166,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.clientSettings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
@@ -216,7 +216,7 @@ export default Vue.extend({
 			const post = data.post;
 			if (post.id == this.post.id) {
 				this.$emit('update:post', post);
-			} else if (post.id == this.post.repost_id) {
+			} else if (post.id == this.post.repostId) {
 				this.post.repost = post;
 			}
 		},
diff --git a/src/web/app/desktop/views/components/posts.vue b/src/web/app/desktop/views/components/posts.vue
index ffceff8762..5031667c7c 100644
--- a/src/web/app/desktop/views/components/posts.vue
+++ b/src/web/app/desktop/views/components/posts.vue
@@ -30,8 +30,8 @@ export default Vue.extend({
 	computed: {
 		_posts(): any[] {
 			return (this.posts as any).map(post => {
-				const date = new Date(post.created_at).getDate();
-				const month = new Date(post.created_at).getMonth() + 1;
+				const date = new Date(post.createdAt).getDate();
+				const month = new Date(post.createdAt).getMonth() + 1;
 				post._date = date;
 				post._datetext = `${month}月 ${date}日`;
 				return post;
diff --git a/src/web/app/desktop/views/components/repost-form.vue b/src/web/app/desktop/views/components/repost-form.vue
index f2774b817c..3a5e3a7c56 100644
--- a/src/web/app/desktop/views/components/repost-form.vue
+++ b/src/web/app/desktop/views/components/repost-form.vue
@@ -29,7 +29,7 @@ export default Vue.extend({
 		ok() {
 			this.wait = true;
 			(this as any).api('posts/create', {
-				repost_id: this.post.id
+				repostId: this.post.id
 			}).then(data => {
 				this.$emit('posted');
 				(this as any).apis.notify('%i18n:desktop.tags.mk-repost-form.success%');
diff --git a/src/web/app/desktop/views/components/settings.2fa.vue b/src/web/app/desktop/views/components/settings.2fa.vue
index 85f2d6ba5e..b8dd1dfd9b 100644
--- a/src/web/app/desktop/views/components/settings.2fa.vue
+++ b/src/web/app/desktop/views/components/settings.2fa.vue
@@ -2,8 +2,8 @@
 <div class="2fa">
 	<p>%i18n:desktop.tags.mk-2fa-setting.intro%<a href="%i18n:desktop.tags.mk-2fa-setting.url%" target="_blank">%i18n:desktop.tags.mk-2fa-setting.detail%</a></p>
 	<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:desktop.tags.mk-2fa-setting.caution%</p></div>
-	<p v-if="!data && !os.i.account.two_factor_enabled"><button @click="register" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.register%</button></p>
-	<template v-if="os.i.account.two_factor_enabled">
+	<p v-if="!data && !os.i.account.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.register%</button></p>
+	<template v-if="os.i.account.twoFactorEnabled">
 		<p>%i18n:desktop.tags.mk-2fa-setting.already-registered%</p>
 		<button @click="unregister" class="ui">%i18n:desktop.tags.mk-2fa-setting.unregister%</button>
 	</template>
@@ -54,7 +54,7 @@ export default Vue.extend({
 					password: password
 				}).then(() => {
 					(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.unregistered%');
-					(this as any).os.i.account.two_factor_enabled = false;
+					(this as any).os.i.account.twoFactorEnabled = false;
 				});
 			});
 		},
@@ -64,7 +64,7 @@ export default Vue.extend({
 				token: this.token
 			}).then(() => {
 				(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.success%');
-				(this as any).os.i.account.two_factor_enabled = true;
+				(this as any).os.i.account.twoFactorEnabled = true;
 			}).catch(() => {
 				(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.failed%');
 			});
diff --git a/src/web/app/desktop/views/components/settings.profile.vue b/src/web/app/desktop/views/components/settings.profile.vue
index 67a211c792..f34d8ff00d 100644
--- a/src/web/app/desktop/views/components/settings.profile.vue
+++ b/src/web/app/desktop/views/components/settings.profile.vue
@@ -24,7 +24,7 @@
 	<button class="ui primary" @click="save">%i18n:desktop.tags.mk-profile-setting.save%</button>
 	<section>
 		<h2>その他</h2>
-		<mk-switch v-model="os.i.account.is_bot" @change="onChangeIsBot" text="このアカウントはbotです"/>
+		<mk-switch v-model="os.i.account.isBot" @change="onChangeIsBot" text="このアカウントはbotです"/>
 	</section>
 </div>
 </template>
@@ -63,7 +63,7 @@ export default Vue.extend({
 		},
 		onChangeIsBot() {
 			(this as any).api('i/update', {
-				is_bot: (this as any).os.i.account.is_bot
+				isBot: (this as any).os.i.account.isBot
 			});
 		}
 	}
diff --git a/src/web/app/desktop/views/components/settings.signins.vue b/src/web/app/desktop/views/components/settings.signins.vue
index ddc567f06f..a414c95c27 100644
--- a/src/web/app/desktop/views/components/settings.signins.vue
+++ b/src/web/app/desktop/views/components/settings.signins.vue
@@ -6,7 +6,7 @@
 			<template v-if="signin.success">%fa:check%</template>
 			<template v-else>%fa:times%</template>
 			<span class="ip">{{ signin.ip }}</span>
-			<mk-time :time="signin.created_at"/>
+			<mk-time :time="signin.createdAt"/>
 		</header>
 		<div class="headers" v-show="signin._show">
 			<tree-view :data="signin.headers"/>
diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue
index 3e6a477ced..cf75e52be2 100644
--- a/src/web/app/desktop/views/components/settings.vue
+++ b/src/web/app/desktop/views/components/settings.vue
@@ -20,7 +20,7 @@
 
 		<section class="web" v-show="page == 'web'">
 			<h1>動作</h1>
-			<mk-switch v-model="os.i.account.client_settings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
+			<mk-switch v-model="os.i.account.clientSettings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
 				<span>ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。</span>
 			</mk-switch>
 			<mk-switch v-model="autoPopout" text="ウィンドウの自動ポップアウト">
@@ -33,11 +33,11 @@
 			<div class="div">
 				<button class="ui button" @click="customizeHome">ホームをカスタマイズ</button>
 			</div>
-			<mk-switch v-model="os.i.account.client_settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
-			<mk-switch v-model="os.i.account.client_settings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
+			<mk-switch v-model="os.i.account.clientSettings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
+			<mk-switch v-model="os.i.account.clientSettings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
 				<span>位置情報が添付された投稿のマップを自動的に展開します。</span>
 			</mk-switch>
-			<mk-switch v-model="os.i.account.client_settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
+			<mk-switch v-model="os.i.account.clientSettings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
 		</section>
 
 		<section class="web" v-show="page == 'web'">
@@ -57,7 +57,7 @@
 
 		<section class="web" v-show="page == 'web'">
 			<h1>モバイル</h1>
-			<mk-switch v-model="os.i.account.client_settings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
+			<mk-switch v-model="os.i.account.clientSettings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
 		</section>
 
 		<section class="web" v-show="page == 'web'">
diff --git a/src/web/app/desktop/views/components/sub-post-content.vue b/src/web/app/desktop/views/components/sub-post-content.vue
index 8c8f42c801..f13822331b 100644
--- a/src/web/app/desktop/views/components/sub-post-content.vue
+++ b/src/web/app/desktop/views/components/sub-post-content.vue
@@ -1,9 +1,9 @@
 <template>
 <div class="mk-sub-post-content">
 	<div class="body">
-		<a class="reply" v-if="post.reply_id">%fa:reply%</a>
+		<a class="reply" v-if="post.replyId">%fa:reply%</a>
 		<mk-post-html :ast="post.ast" :i="os.i"/>
-		<a class="rp" v-if="post.repost_id" :href="`/post:${post.repost_id}`">RP: ...</a>
+		<a class="rp" v-if="post.repostId" :href="`/post:${post.repostId}`">RP: ...</a>
 		<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
 	</div>
 	<details v-if="post.media">
diff --git a/src/web/app/desktop/views/components/timeline.vue b/src/web/app/desktop/views/components/timeline.vue
index 47a9688b6d..c0eae2cd9e 100644
--- a/src/web/app/desktop/views/components/timeline.vue
+++ b/src/web/app/desktop/views/components/timeline.vue
@@ -34,7 +34,7 @@ export default Vue.extend({
 	},
 	computed: {
 		alone(): boolean {
-			return (this as any).os.i.following_count == 0;
+			return (this as any).os.i.followingCount == 0;
 		}
 	},
 	mounted() {
@@ -107,7 +107,7 @@ export default Vue.extend({
 			this.fetch();
 		},
 		onScroll() {
-			if ((this as any).os.i.account.client_settings.fetchOnScroll !== false) {
+			if ((this as any).os.i.account.clientSettings.fetchOnScroll !== false) {
 				const current = window.scrollY + window.innerHeight;
 				if (current > document.body.offsetHeight - 8) this.more();
 			}
diff --git a/src/web/app/desktop/views/components/ui.header.vue b/src/web/app/desktop/views/components/ui.header.vue
index 8af0e2fbed..7e337d2ae5 100644
--- a/src/web/app/desktop/views/components/ui.header.vue
+++ b/src/web/app/desktop/views/components/ui.header.vue
@@ -44,9 +44,9 @@ export default Vue.extend({
 	},
 	mounted() {
 		if ((this as any).os.isSignedIn) {
-			const ago = (new Date().getTime() - new Date((this as any).os.i.account.last_used_at).getTime()) / 1000
+			const ago = (new Date().getTime() - new Date((this as any).os.i.account.lastUsedAt).getTime()) / 1000
 			const isHisasiburi = ago >= 3600;
-			(this as any).os.i.account.last_used_at = new Date();
+			(this as any).os.i.account.lastUsedAt = new Date();
 			if (isHisasiburi) {
 				(this.$refs.welcomeback as any).style.display = 'block';
 				(this.$refs.main as any).style.overflow = 'hidden';
diff --git a/src/web/app/desktop/views/components/user-preview.vue b/src/web/app/desktop/views/components/user-preview.vue
index 24d613f120..4535ad8902 100644
--- a/src/web/app/desktop/views/components/user-preview.vue
+++ b/src/web/app/desktop/views/components/user-preview.vue
@@ -12,13 +12,13 @@
 		<div class="description">{{ u.description }}</div>
 		<div class="status">
 			<div>
-				<p>投稿</p><a>{{ u.posts_count }}</a>
+				<p>投稿</p><a>{{ u.postsCount }}</a>
 			</div>
 			<div>
-				<p>フォロー</p><a>{{ u.following_count }}</a>
+				<p>フォロー</p><a>{{ u.followingCount }}</a>
 			</div>
 			<div>
-				<p>フォロワー</p><a>{{ u.followers_count }}</a>
+				<p>フォロワー</p><a>{{ u.followersCount }}</a>
 			</div>
 		</div>
 		<mk-follow-button v-if="os.isSignedIn && user.id != os.i.id" :user="u"/>
@@ -58,7 +58,7 @@ export default Vue.extend({
 		} else {
 			const query = this.user[0] == '@' ?
 				parseAcct(this.user[0].substr(1)) :
-				{ user_id: this.user[0] };
+				{ userId: this.user[0] };
 
 			(this as any).api('users/show', query).then(user => {
 				this.u = user;
diff --git a/src/web/app/desktop/views/components/widget-container.vue b/src/web/app/desktop/views/components/widget-container.vue
index dd42be63bb..68c5bcb8dc 100644
--- a/src/web/app/desktop/views/components/widget-container.vue
+++ b/src/web/app/desktop/views/components/widget-container.vue
@@ -24,8 +24,8 @@ export default Vue.extend({
 	computed: {
 		withGradient(): boolean {
 			return (this as any).os.isSignedIn
-				? (this as any).os.i.account.client_settings.gradientWindowHeader != null
-					? (this as any).os.i.account.client_settings.gradientWindowHeader
+				? (this as any).os.i.account.clientSettings.gradientWindowHeader != null
+					? (this as any).os.i.account.clientSettings.gradientWindowHeader
 					: false
 				: false;
 		}
diff --git a/src/web/app/desktop/views/components/window.vue b/src/web/app/desktop/views/components/window.vue
index 75f725d4b0..48dc46febd 100644
--- a/src/web/app/desktop/views/components/window.vue
+++ b/src/web/app/desktop/views/components/window.vue
@@ -92,8 +92,8 @@ export default Vue.extend({
 		},
 		withGradient(): boolean {
 			return (this as any).os.isSignedIn
-				? (this as any).os.i.account.client_settings.gradientWindowHeader != null
-					? (this as any).os.i.account.client_settings.gradientWindowHeader
+				? (this as any).os.i.account.clientSettings.gradientWindowHeader != null
+					? (this as any).os.i.account.clientSettings.gradientWindowHeader
 					: false
 				: false;
 		}
diff --git a/src/web/app/desktop/views/pages/home.vue b/src/web/app/desktop/views/pages/home.vue
index e1464bab1d..69e134f79f 100644
--- a/src/web/app/desktop/views/pages/home.vue
+++ b/src/web/app/desktop/views/pages/home.vue
@@ -45,7 +45,7 @@ export default Vue.extend({
 		},
 
 		onStreamPost(post) {
-			if (document.hidden && post.user_id != (this as any).os.i.id) {
+			if (document.hidden && post.userId != (this as any).os.i.id) {
 				this.unreadCount++;
 				document.title = `(${this.unreadCount}) ${getPostSummary(post)}`;
 			}
diff --git a/src/web/app/desktop/views/pages/post.vue b/src/web/app/desktop/views/pages/post.vue
index c7b8729b72..dbd707e049 100644
--- a/src/web/app/desktop/views/pages/post.vue
+++ b/src/web/app/desktop/views/pages/post.vue
@@ -31,7 +31,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('posts/show', {
-				post_id: this.$route.params.post
+				postId: this.$route.params.post
 			}).then(post => {
 				this.post = post;
 				this.fetching = false;
diff --git a/src/web/app/desktop/views/pages/user/user.followers-you-know.vue b/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
index 80b38e8acc..9f67f5cf76 100644
--- a/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
+++ b/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
@@ -28,7 +28,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/followers', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			iknow: true,
 			limit: 16
 		}).then(x => {
diff --git a/src/web/app/desktop/views/pages/user/user.friends.vue b/src/web/app/desktop/views/pages/user/user.friends.vue
index 57e6def27b..cc0bcef257 100644
--- a/src/web/app/desktop/views/pages/user/user.friends.vue
+++ b/src/web/app/desktop/views/pages/user/user.friends.vue
@@ -35,7 +35,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/get_frequently_replied_users', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			limit: 4
 		}).then(docs => {
 			this.users = docs.map(doc => doc.user);
diff --git a/src/web/app/desktop/views/pages/user/user.home.vue b/src/web/app/desktop/views/pages/user/user.home.vue
index 2483a6c726..071c9bb61c 100644
--- a/src/web/app/desktop/views/pages/user/user.home.vue
+++ b/src/web/app/desktop/views/pages/user/user.home.vue
@@ -5,16 +5,16 @@
 			<x-profile :user="user"/>
 			<x-photos :user="user"/>
 			<x-followers-you-know v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
-			<p v-if="user.host === null">%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.account.last_used_at"/></b></p>
+			<p v-if="user.host === null">%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.account.lastUsedAt"/></b></p>
 		</div>
 	</div>
 	<main>
-		<mk-post-detail v-if="user.pinned_post" :post="user.pinned_post" :compact="true"/>
+		<mk-post-detail v-if="user.pinnedPost" :post="user.pinnedPost" :compact="true"/>
 		<x-timeline class="timeline" ref="tl" :user="user"/>
 	</main>
 	<div>
 		<div ref="right">
-			<mk-calendar @chosen="warp" :start="new Date(user.created_at)"/>
+			<mk-calendar @chosen="warp" :start="new Date(user.createdAt)"/>
 			<mk-activity :user="user"/>
 			<x-friends :user="user"/>
 			<div class="nav"><mk-nav/></div>
diff --git a/src/web/app/desktop/views/pages/user/user.photos.vue b/src/web/app/desktop/views/pages/user/user.photos.vue
index db29a9945a..2baf042bc0 100644
--- a/src/web/app/desktop/views/pages/user/user.photos.vue
+++ b/src/web/app/desktop/views/pages/user/user.photos.vue
@@ -23,7 +23,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/posts', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			with_media: true,
 			limit: 9
 		}).then(posts => {
diff --git a/src/web/app/desktop/views/pages/user/user.profile.vue b/src/web/app/desktop/views/pages/user/user.profile.vue
index b51aae18fa..0d91df2a59 100644
--- a/src/web/app/desktop/views/pages/user/user.profile.vue
+++ b/src/web/app/desktop/views/pages/user/user.profile.vue
@@ -11,12 +11,12 @@
 		<p>%fa:birthday-cake%{{ user.account.profile.birthday.replace('-', '年').replace('-', '月') + '日' }} ({{ age }}歳)</p>
 	</div>
 	<div class="twitter" v-if="user.host === null && user.account.twitter">
-		<p>%fa:B twitter%<a :href="`https://twitter.com/${user.account.twitter.screen_name}`" target="_blank">@{{ user.account.twitter.screen_name }}</a></p>
+		<p>%fa:B twitter%<a :href="`https://twitter.com/${user.account.twitter.screenName}`" target="_blank">@{{ user.account.twitter.screenName }}</a></p>
 	</div>
 	<div class="status">
-		<p class="posts-count">%fa:angle-right%<a>{{ user.posts_count }}</a><b>投稿</b></p>
-		<p class="following">%fa:angle-right%<a @click="showFollowing">{{ user.following_count }}</a>人を<b>フォロー</b></p>
-		<p class="followers">%fa:angle-right%<a @click="showFollowers">{{ user.followers_count }}</a>人の<b>フォロワー</b></p>
+		<p class="posts-count">%fa:angle-right%<a>{{ user.postsCount }}</a><b>投稿</b></p>
+		<p class="following">%fa:angle-right%<a @click="showFollowing">{{ user.followingCount }}</a>人を<b>フォロー</b></p>
+		<p class="followers">%fa:angle-right%<a @click="showFollowers">{{ user.followersCount }}</a>人の<b>フォロワー</b></p>
 	</div>
 </div>
 </template>
@@ -49,7 +49,7 @@ export default Vue.extend({
 
 		mute() {
 			(this as any).api('mute/create', {
-				user_id: this.user.id
+				userId: this.user.id
 			}).then(() => {
 				this.user.is_muted = true;
 			}, () => {
@@ -59,7 +59,7 @@ export default Vue.extend({
 
 		unmute() {
 			(this as any).api('mute/delete', {
-				user_id: this.user.id
+				userId: this.user.id
 			}).then(() => {
 				this.user.is_muted = false;
 			}, () => {
diff --git a/src/web/app/desktop/views/pages/user/user.timeline.vue b/src/web/app/desktop/views/pages/user/user.timeline.vue
index 60eef8951b..1f0d0b1985 100644
--- a/src/web/app/desktop/views/pages/user/user.timeline.vue
+++ b/src/web/app/desktop/views/pages/user/user.timeline.vue
@@ -61,7 +61,7 @@ export default Vue.extend({
 		},
 		fetch(cb?) {
 			(this as any).api('users/posts', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				until_date: this.date ? this.date.getTime() : undefined,
 				with_replies: this.mode == 'with-replies'
 			}).then(posts => {
@@ -74,7 +74,7 @@ export default Vue.extend({
 			if (this.moreFetching || this.fetching || this.posts.length == 0) return;
 			this.moreFetching = true;
 			(this as any).api('users/posts', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				with_replies: this.mode == 'with-replies',
 				until_id: this.posts[this.posts.length - 1].id
 			}).then(posts => {
diff --git a/src/web/app/desktop/views/widgets/channel.channel.form.vue b/src/web/app/desktop/views/widgets/channel.channel.form.vue
index 392ba5924b..aaf327f1ef 100644
--- a/src/web/app/desktop/views/widgets/channel.channel.form.vue
+++ b/src/web/app/desktop/views/widgets/channel.channel.form.vue
@@ -30,8 +30,8 @@ export default Vue.extend({
 
 			(this as any).api('posts/create', {
 				text: this.text,
-				reply_id: reply ? reply.id : undefined,
-				channel_id: (this.$parent as any).channel.id
+				replyId: reply ? reply.id : undefined,
+				channelId: (this.$parent as any).channel.id
 			}).then(data => {
 				this.text = '';
 			}).catch(err => {
diff --git a/src/web/app/desktop/views/widgets/channel.channel.vue b/src/web/app/desktop/views/widgets/channel.channel.vue
index de5885bfc1..e9fb9e3fd7 100644
--- a/src/web/app/desktop/views/widgets/channel.channel.vue
+++ b/src/web/app/desktop/views/widgets/channel.channel.vue
@@ -44,7 +44,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('channels/posts', {
-				channel_id: this.channel.id
+				channelId: this.channel.id
 			}).then(posts => {
 				this.posts = posts;
 				this.fetching = false;
diff --git a/src/web/app/desktop/views/widgets/channel.vue b/src/web/app/desktop/views/widgets/channel.vue
index fc143bb1df..c9b62dfeab 100644
--- a/src/web/app/desktop/views/widgets/channel.vue
+++ b/src/web/app/desktop/views/widgets/channel.vue
@@ -48,7 +48,7 @@ export default define({
 			this.fetching = true;
 
 			(this as any).api('channels/show', {
-				channel_id: this.props.channel
+				channelId: this.props.channel
 			}).then(channel => {
 				this.channel = channel;
 				this.fetching = false;
diff --git a/src/web/app/dev/views/app.vue b/src/web/app/dev/views/app.vue
index 2c2a3c83ce..a35b032b73 100644
--- a/src/web/app/dev/views/app.vue
+++ b/src/web/app/dev/views/app.vue
@@ -28,7 +28,7 @@ export default Vue.extend({
 		fetch() {
 			this.fetching = true;
 			(this as any).api('app/show', {
-				app_id: this.$route.params.id
+				appId: this.$route.params.id
 			}).then(app => {
 				this.app = app;
 				this.fetching = false;
diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue
index 1a796299cb..cd07cc4d49 100644
--- a/src/web/app/dev/views/new-app.vue
+++ b/src/web/app/dev/views/new-app.vue
@@ -77,8 +77,8 @@ export default Vue.extend({
 
 			this.nidState = 'wait';
 
-			(this as any).api('app/name_id/available', {
-				name_id: this.nid
+			(this as any).api('app/nameId/available', {
+				nameId: this.nid
 			}).then(result => {
 				this.nidState = result.available ? 'ok' : 'unavailable';
 			}).catch(err => {
@@ -90,7 +90,7 @@ export default Vue.extend({
 		onSubmit() {
 			(this as any).api('app/create', {
 				name: this.name,
-				name_id: this.nid,
+				nameId: this.nid,
 				description: this.description,
 				callback_url: this.cb,
 				permission: this.permission
diff --git a/src/web/app/mobile/api/post.ts b/src/web/app/mobile/api/post.ts
index 9b78ce10c2..841103fee1 100644
--- a/src/web/app/mobile/api/post.ts
+++ b/src/web/app/mobile/api/post.ts
@@ -18,7 +18,7 @@ export default (os) => (opts) => {
 		const text = window.prompt(`「${getPostSummary(o.repost)}」をRepost`);
 		if (text == null) return;
 		os.api('posts/create', {
-			repost_id: o.repost.id,
+			repostId: o.repost.id,
 			text: text == '' ? undefined : text
 		});
 	} else {
diff --git a/src/web/app/mobile/views/components/activity.vue b/src/web/app/mobile/views/components/activity.vue
index b50044b3de..2e44017e77 100644
--- a/src/web/app/mobile/views/components/activity.vue
+++ b/src/web/app/mobile/views/components/activity.vue
@@ -29,7 +29,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('aggregation/users/activity', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			limit: 30
 		}).then(data => {
 			data.forEach(d => d.total = d.posts + d.replies + d.reposts);
diff --git a/src/web/app/mobile/views/components/drive.file-detail.vue b/src/web/app/mobile/views/components/drive.file-detail.vue
index e41ebbb451..f3274f677f 100644
--- a/src/web/app/mobile/views/components/drive.file-detail.vue
+++ b/src/web/app/mobile/views/components/drive.file-detail.vue
@@ -29,7 +29,7 @@
 			<span class="separator"></span>
 			<span class="data-size">{{ file.datasize | bytes }}</span>
 			<span class="separator"></span>
-			<span class="created-at" @click="showCreatedAt">%fa:R clock%<mk-time :time="file.created_at"/></span>
+			<span class="created-at" @click="showCreatedAt">%fa:R clock%<mk-time :time="file.createdAt"/></span>
 		</div>
 	</div>
 	<div class="menu">
@@ -86,8 +86,8 @@ export default Vue.extend({
 			return this.file.type.split('/')[0];
 		},
 		style(): any {
-			return this.file.properties.average_color ? {
-				'background-color': `rgb(${ this.file.properties.average_color.join(',') })`
+			return this.file.properties.avgColor ? {
+				'background-color': `rgb(${ this.file.properties.avgColor.join(',') })`
 			} : {};
 		}
 	},
@@ -96,7 +96,7 @@ export default Vue.extend({
 			const name = window.prompt('名前を変更', this.file.name);
 			if (name == null || name == '' || name == this.file.name) return;
 			(this as any).api('drive/files/update', {
-				file_id: this.file.id,
+				fileId: this.file.id,
 				name: name
 			}).then(() => {
 				this.browser.cf(this.file, true);
@@ -105,15 +105,15 @@ export default Vue.extend({
 		move() {
 			(this as any).apis.chooseDriveFolder().then(folder => {
 				(this as any).api('drive/files/update', {
-					file_id: this.file.id,
-					folder_id: folder == null ? null : folder.id
+					fileId: this.file.id,
+					folderId: folder == null ? null : folder.id
 				}).then(() => {
 					this.browser.cf(this.file, true);
 				});
 			});
 		},
 		showCreatedAt() {
-			alert(new Date(this.file.created_at).toLocaleString());
+			alert(new Date(this.file.createdAt).toLocaleString());
 		},
 		onImageLoaded() {
 			const self = this;
diff --git a/src/web/app/mobile/views/components/drive.file.vue b/src/web/app/mobile/views/components/drive.file.vue
index db73816282..7d1957042b 100644
--- a/src/web/app/mobile/views/components/drive.file.vue
+++ b/src/web/app/mobile/views/components/drive.file.vue
@@ -19,7 +19,7 @@
 				<p class="data-size">{{ file.datasize | bytes }}</p>
 				<p class="separator"></p>
 				<p class="created-at">
-					%fa:R clock%<mk-time :time="file.created_at"/>
+					%fa:R clock%<mk-time :time="file.createdAt"/>
 				</p>
 			</footer>
 		</div>
@@ -42,7 +42,7 @@ export default Vue.extend({
 		},
 		thumbnail(): any {
 			return {
-				'background-color': this.file.properties.average_color ? `rgb(${this.file.properties.average_color.join(',')})` : 'transparent',
+				'background-color': this.file.properties.avgColor ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
 				'background-image': `url(${this.file.url}?thumbnail&size=128)`
 			};
 		}
diff --git a/src/web/app/mobile/views/components/drive.vue b/src/web/app/mobile/views/components/drive.vue
index 696c63e2a4..dd4d97e960 100644
--- a/src/web/app/mobile/views/components/drive.vue
+++ b/src/web/app/mobile/views/components/drive.vue
@@ -129,7 +129,7 @@ export default Vue.extend({
 
 		onStreamDriveFileUpdated(file) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != file.folder_id) {
+			if (current != file.folderId) {
 				this.removeFile(file);
 			} else {
 				this.addFile(file, true);
@@ -142,7 +142,7 @@ export default Vue.extend({
 
 		onStreamDriveFolderUpdated(folder) {
 			const current = this.folder ? this.folder.id : null;
-			if (current != folder.parent_id) {
+			if (current != folder.parentId) {
 				this.removeFolder(folder);
 			} else {
 				this.addFolder(folder, true);
@@ -167,7 +167,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('drive/folders/show', {
-				folder_id: target
+				folderId: target
 			}).then(folder => {
 				this.folder = folder;
 				this.hierarchyFolders = [];
@@ -182,7 +182,7 @@ export default Vue.extend({
 		addFolder(folder, unshift = false) {
 			const current = this.folder ? this.folder.id : null;
 			// 追加しようとしているフォルダが、今居る階層とは違う階層のものだったら中断
-			if (current != folder.parent_id) return;
+			if (current != folder.parentId) return;
 
 			// 追加しようとしているフォルダを既に所有してたら中断
 			if (this.folders.some(f => f.id == folder.id)) return;
@@ -197,7 +197,7 @@ export default Vue.extend({
 		addFile(file, unshift = false) {
 			const current = this.folder ? this.folder.id : null;
 			// 追加しようとしているファイルが、今居る階層とは違う階層のものだったら中断
-			if (current != file.folder_id) return;
+			if (current != file.folderId) return;
 
 			if (this.files.some(f => f.id == file.id)) {
 				const exist = this.files.map(f => f.id).indexOf(file.id);
@@ -262,7 +262,7 @@ export default Vue.extend({
 
 			// フォルダ一覧取得
 			(this as any).api('drive/folders', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: foldersMax + 1
 			}).then(folders => {
 				if (folders.length == foldersMax + 1) {
@@ -275,7 +275,7 @@ export default Vue.extend({
 
 			// ファイル一覧取得
 			(this as any).api('drive/files', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: filesMax + 1
 			}).then(files => {
 				if (files.length == filesMax + 1) {
@@ -318,7 +318,7 @@ export default Vue.extend({
 
 			// ファイル一覧取得
 			(this as any).api('drive/files', {
-				folder_id: this.folder ? this.folder.id : null,
+				folderId: this.folder ? this.folder.id : null,
 				limit: max + 1,
 				until_id: this.files[this.files.length - 1].id
 			}).then(files => {
@@ -357,7 +357,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('drive/files/show', {
-				file_id: file
+				fileId: file
 			}).then(file => {
 				this.file = file;
 				this.folder = null;
@@ -405,7 +405,7 @@ export default Vue.extend({
 			if (name == null || name == '') return;
 			(this as any).api('drive/folders/create', {
 				name: name,
-				parent_id: this.folder ? this.folder.id : undefined
+				parentId: this.folder ? this.folder.id : undefined
 			}).then(folder => {
 				this.addFolder(folder, true);
 			});
@@ -420,7 +420,7 @@ export default Vue.extend({
 			if (name == null || name == '') return;
 			(this as any).api('drive/folders/update', {
 				name: name,
-				folder_id: this.folder.id
+				folderId: this.folder.id
 			}).then(folder => {
 				this.cd(folder);
 			});
@@ -433,8 +433,8 @@ export default Vue.extend({
 			}
 			(this as any).apis.chooseDriveFolder().then(folder => {
 				(this as any).api('drive/folders/update', {
-					parent_id: folder ? folder.id : null,
-					folder_id: this.folder.id
+					parentId: folder ? folder.id : null,
+					folderId: this.folder.id
 				}).then(folder => {
 					this.cd(folder);
 				});
@@ -446,7 +446,7 @@ export default Vue.extend({
 			if (url == null || url == '') return;
 			(this as any).api('drive/files/upload_from_url', {
 				url: url,
-				folder_id: this.folder ? this.folder.id : undefined
+				folderId: this.folder ? this.folder.id : undefined
 			});
 			alert('アップロードをリクエストしました。アップロードが完了するまで時間がかかる場合があります。');
 		},
diff --git a/src/web/app/mobile/views/components/follow-button.vue b/src/web/app/mobile/views/components/follow-button.vue
index fb6eaa39c6..838ea404eb 100644
--- a/src/web/app/mobile/views/components/follow-button.vue
+++ b/src/web/app/mobile/views/components/follow-button.vue
@@ -57,7 +57,7 @@ export default Vue.extend({
 			this.wait = true;
 			if (this.user.is_following) {
 				(this as any).api('following/delete', {
-					user_id: this.user.id
+					userId: this.user.id
 				}).then(() => {
 					this.user.is_following = false;
 				}).catch(err => {
@@ -67,7 +67,7 @@ export default Vue.extend({
 				});
 			} else {
 				(this as any).api('following/create', {
-					user_id: this.user.id
+					userId: this.user.id
 				}).then(() => {
 					this.user.is_following = true;
 				}).catch(err => {
diff --git a/src/web/app/mobile/views/components/media-image.vue b/src/web/app/mobile/views/components/media-image.vue
index faf8bad48a..cfc2134988 100644
--- a/src/web/app/mobile/views/components/media-image.vue
+++ b/src/web/app/mobile/views/components/media-image.vue
@@ -10,7 +10,7 @@ export default Vue.extend({
 	computed: {
 		style(): any {
 			return {
-				'background-color': this.image.properties.average_color ? `rgb(${this.image.properties.average_color.join(',')})` : 'transparent',
+				'background-color': this.image.properties.avgColor ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
 				'background-image': `url(${this.image.url}?thumbnail&size=512)`
 			};
 		}
diff --git a/src/web/app/mobile/views/components/notification.vue b/src/web/app/mobile/views/components/notification.vue
index 150ac0fd8b..aac8f82900 100644
--- a/src/web/app/mobile/views/components/notification.vue
+++ b/src/web/app/mobile/views/components/notification.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-notification">
 	<div class="notification reaction" v-if="notification.type == 'reaction'">
-		<mk-time :time="notification.created_at"/>
+		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
 			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
@@ -18,7 +18,7 @@
 	</div>
 
 	<div class="notification repost" v-if="notification.type == 'repost'">
-		<mk-time :time="notification.created_at"/>
+		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
 			<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
@@ -38,7 +38,7 @@
 	</template>
 
 	<div class="notification follow" v-if="notification.type == 'follow'">
-		<mk-time :time="notification.created_at"/>
+		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
 			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
@@ -59,7 +59,7 @@
 	</template>
 
 	<div class="notification poll_vote" v-if="notification.type == 'poll_vote'">
-		<mk-time :time="notification.created_at"/>
+		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
 			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
diff --git a/src/web/app/mobile/views/components/notifications.vue b/src/web/app/mobile/views/components/notifications.vue
index 1cd6e2bc13..4365198f16 100644
--- a/src/web/app/mobile/views/components/notifications.vue
+++ b/src/web/app/mobile/views/components/notifications.vue
@@ -34,8 +34,8 @@ export default Vue.extend({
 	computed: {
 		_notifications(): any[] {
 			return (this.notifications as any).map(notification => {
-				const date = new Date(notification.created_at).getDate();
-				const month = new Date(notification.created_at).getMonth() + 1;
+				const date = new Date(notification.createdAt).getDate();
+				const month = new Date(notification.createdAt).getMonth() + 1;
 				notification._date = date;
 				notification._datetext = `${month}月 ${date}日`;
 				return notification;
diff --git a/src/web/app/mobile/views/components/post-card.vue b/src/web/app/mobile/views/components/post-card.vue
index 8ca7550c2e..10dfd92415 100644
--- a/src/web/app/mobile/views/components/post-card.vue
+++ b/src/web/app/mobile/views/components/post-card.vue
@@ -7,7 +7,7 @@
 		<div>
 			{{ text }}
 		</div>
-		<mk-time :time="post.created_at"/>
+		<mk-time :time="post.createdAt"/>
 	</a>
 </div>
 </template>
diff --git a/src/web/app/mobile/views/components/post-detail.sub.vue b/src/web/app/mobile/views/components/post-detail.sub.vue
index 6906cf570e..427e054fd6 100644
--- a/src/web/app/mobile/views/components/post-detail.sub.vue
+++ b/src/web/app/mobile/views/components/post-detail.sub.vue
@@ -8,7 +8,7 @@
 			<router-link class="name" :to="`/@${acct}`">{{ post.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="time" :to="`/@${acct}/${post.id}`">
-				<mk-time :time="post.created_at"/>
+				<mk-time :time="post.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index b5c9158300..9a8c33a80d 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -2,7 +2,7 @@
 <div class="mk-post-detail">
 	<button
 		class="more"
-		v-if="p.reply && p.reply.reply_id && context == null"
+		v-if="p.reply && p.reply.replyId && context == null"
 		@click="fetchContext"
 		:disabled="fetchingContext"
 	>
@@ -54,7 +54,7 @@
 			</div>
 		</div>
 		<router-link class="time" :to="`/@${pAcct}/${p.id}`">
-			<mk-time :time="p.created_at" mode="detail"/>
+			<mk-time :time="p.createdAt" mode="detail"/>
 		</router-link>
 		<footer>
 			<mk-reactions-viewer :post="p"/>
@@ -115,7 +115,7 @@ export default Vue.extend({
 		isRepost(): boolean {
 			return (this.post.repost &&
 				this.post.text == null &&
-				this.post.media_ids == null &&
+				this.post.mediaIds == null &&
 				this.post.poll == null);
 		},
 		p(): any {
@@ -142,7 +142,7 @@ export default Vue.extend({
 		// Get replies
 		if (!this.compact) {
 			(this as any).api('posts/replies', {
-				post_id: this.p.id,
+				postId: this.p.id,
 				limit: 8
 			}).then(replies => {
 				this.replies = replies;
@@ -151,7 +151,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.clientSettings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
@@ -173,7 +173,7 @@ export default Vue.extend({
 
 			// Fetch context
 			(this as any).api('posts/context', {
-				post_id: this.p.reply_id
+				postId: this.p.replyId
 			}).then(context => {
 				this.contextFetching = false;
 				this.context = context.reverse();
diff --git a/src/web/app/mobile/views/components/post-form.vue b/src/web/app/mobile/views/components/post-form.vue
index 2aa3c6f6c0..929dc5933b 100644
--- a/src/web/app/mobile/views/components/post-form.vue
+++ b/src/web/app/mobile/views/components/post-form.vue
@@ -111,11 +111,11 @@ export default Vue.extend({
 		},
 		post() {
 			this.posting = true;
-			const viaMobile = (this as any).os.i.account.client_settings.disableViaMobile !== true;
+			const viaMobile = (this as any).os.i.account.clientSettings.disableViaMobile !== true;
 			(this as any).api('posts/create', {
 				text: this.text == '' ? undefined : this.text,
-				media_ids: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
-				reply_id: this.reply ? this.reply.id : undefined,
+				mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
+				replyId: this.reply ? this.reply.id : undefined,
 				poll: this.poll ? (this.$refs.poll as any).get() : undefined,
 				geo: this.geo ? {
 					latitude: this.geo.latitude,
@@ -126,7 +126,7 @@ export default Vue.extend({
 					heading: isNaN(this.geo.heading) ? null : this.geo.heading,
 					speed: this.geo.speed,
 				} : null,
-				via_mobile: viaMobile
+				viaMobile: viaMobile
 			}).then(data => {
 				this.$emit('post');
 				this.$destroy();
diff --git a/src/web/app/mobile/views/components/post-preview.vue b/src/web/app/mobile/views/components/post-preview.vue
index 0bd0a355b3..e640843419 100644
--- a/src/web/app/mobile/views/components/post-preview.vue
+++ b/src/web/app/mobile/views/components/post-preview.vue
@@ -8,7 +8,7 @@
 			<router-link class="name" :to="`/@${acct}`">{{ post.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="time" :to="`/@${acct}/${post.id}`">
-				<mk-time :time="post.created_at"/>
+				<mk-time :time="post.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
diff --git a/src/web/app/mobile/views/components/post.sub.vue b/src/web/app/mobile/views/components/post.sub.vue
index b6ee7c1e08..8a11239da7 100644
--- a/src/web/app/mobile/views/components/post.sub.vue
+++ b/src/web/app/mobile/views/components/post.sub.vue
@@ -8,7 +8,7 @@
 			<router-link class="name" :to="`/@${acct}`">{{ post.user.name }}</router-link>
 			<span class="username">@{{ acct }}</span>
 			<router-link class="created-at" :to="`/@${acct}/${post.id}`">
-				<mk-time :time="post.created_at"/>
+				<mk-time :time="post.createdAt"/>
 			</router-link>
 		</header>
 		<div class="body">
diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue
index e5bc964792..243e7d9c2e 100644
--- a/src/web/app/mobile/views/components/post.vue
+++ b/src/web/app/mobile/views/components/post.vue
@@ -13,7 +13,7 @@
 			<router-link class="name" :to="`/@${acct}`">{{ post.user.name }}</router-link>
 			<span>{{ '%i18n:mobile.tags.mk-timeline-post.reposted-by%'.substr('%i18n:mobile.tags.mk-timeline-post.reposted-by%'.indexOf('}') + 1) }}</span>
 		</p>
-		<mk-time :time="post.created_at"/>
+		<mk-time :time="post.createdAt"/>
 	</div>
 	<article>
 		<router-link class="avatar-anchor" :to="`/@${pAcct}`">
@@ -22,12 +22,12 @@
 		<div class="main">
 			<header>
 				<router-link class="name" :to="`/@${pAcct}`">{{ p.user.name }}</router-link>
-				<span class="is-bot" v-if="p.user.host === null && p.user.account.is_bot">bot</span>
+				<span class="is-bot" v-if="p.user.host === null && p.user.account.isBot">bot</span>
 				<span class="username">@{{ pAcct }}</span>
 				<div class="info">
-					<span class="mobile" v-if="p.via_mobile">%fa:mobile-alt%</span>
+					<span class="mobile" v-if="p.viaMobile">%fa:mobile-alt%</span>
 					<router-link class="created-at" :to="url">
-						<mk-time :time="p.created_at"/>
+						<mk-time :time="p.createdAt"/>
 					</router-link>
 				</div>
 			</header>
@@ -103,7 +103,7 @@ export default Vue.extend({
 		isRepost(): boolean {
 			return (this.post.repost &&
 				this.post.text == null &&
-				this.post.media_ids == null &&
+				this.post.mediaIds == null &&
 				this.post.poll == null);
 		},
 		p(): any {
@@ -144,7 +144,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.clientSettings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
@@ -194,7 +194,7 @@ export default Vue.extend({
 			const post = data.post;
 			if (post.id == this.post.id) {
 				this.$emit('update:post', post);
-			} else if (post.id == this.post.repost_id) {
+			} else if (post.id == this.post.repostId) {
 				this.post.repost = post;
 			}
 		},
diff --git a/src/web/app/mobile/views/components/posts.vue b/src/web/app/mobile/views/components/posts.vue
index 7e71fa0982..4695f1beaa 100644
--- a/src/web/app/mobile/views/components/posts.vue
+++ b/src/web/app/mobile/views/components/posts.vue
@@ -28,8 +28,8 @@ export default Vue.extend({
 	computed: {
 		_posts(): any[] {
 			return (this.posts as any).map(post => {
-				const date = new Date(post.created_at).getDate();
-				const month = new Date(post.created_at).getMonth() + 1;
+				const date = new Date(post.createdAt).getDate();
+				const month = new Date(post.createdAt).getMonth() + 1;
 				post._date = date;
 				post._datetext = `${month}月 ${date}日`;
 				return post;
diff --git a/src/web/app/mobile/views/components/sub-post-content.vue b/src/web/app/mobile/views/components/sub-post-content.vue
index 389fc420ea..b95883de77 100644
--- a/src/web/app/mobile/views/components/sub-post-content.vue
+++ b/src/web/app/mobile/views/components/sub-post-content.vue
@@ -1,9 +1,9 @@
 <template>
 <div class="mk-sub-post-content">
 	<div class="body">
-		<a class="reply" v-if="post.reply_id">%fa:reply%</a>
+		<a class="reply" v-if="post.replyId">%fa:reply%</a>
 		<mk-post-html v-if="post.ast" :ast="post.ast" :i="os.i"/>
-		<a class="rp" v-if="post.repost_id">RP: ...</a>
+		<a class="rp" v-if="post.repostId">RP: ...</a>
 	</div>
 	<details v-if="post.media">
 		<summary>({{ post.media.length }}個のメディア)</summary>
diff --git a/src/web/app/mobile/views/components/timeline.vue b/src/web/app/mobile/views/components/timeline.vue
index c0e766523f..999f4a1f1e 100644
--- a/src/web/app/mobile/views/components/timeline.vue
+++ b/src/web/app/mobile/views/components/timeline.vue
@@ -41,7 +41,7 @@ export default Vue.extend({
 	},
 	computed: {
 		alone(): boolean {
-			return (this as any).os.i.following_count == 0;
+			return (this as any).os.i.followingCount == 0;
 		}
 	},
 	mounted() {
diff --git a/src/web/app/mobile/views/components/ui.header.vue b/src/web/app/mobile/views/components/ui.header.vue
index 66e10a0f8a..2bf47a90a9 100644
--- a/src/web/app/mobile/views/components/ui.header.vue
+++ b/src/web/app/mobile/views/components/ui.header.vue
@@ -57,9 +57,9 @@ export default Vue.extend({
 				}
 			});
 
-			const ago = (new Date().getTime() - new Date((this as any).os.i.account.last_used_at).getTime()) / 1000
+			const ago = (new Date().getTime() - new Date((this as any).os.i.account.lastUsedAt).getTime()) / 1000
 			const isHisasiburi = ago >= 3600;
-			(this as any).os.i.account.last_used_at = new Date();
+			(this as any).os.i.account.lastUsedAt = new Date();
 			if (isHisasiburi) {
 				(this.$refs.welcomeback as any).style.display = 'block';
 				(this.$refs.main as any).style.overflow = 'hidden';
diff --git a/src/web/app/mobile/views/components/user-timeline.vue b/src/web/app/mobile/views/components/user-timeline.vue
index 39f959187c..73ff440dc2 100644
--- a/src/web/app/mobile/views/components/user-timeline.vue
+++ b/src/web/app/mobile/views/components/user-timeline.vue
@@ -33,7 +33,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/posts', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			with_media: this.withMedia,
 			limit: limit + 1
 		}).then(posts => {
@@ -50,7 +50,7 @@ export default Vue.extend({
 		more() {
 			this.moreFetching = true;
 			(this as any).api('users/posts', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				with_media: this.withMedia,
 				limit: limit + 1,
 				until_id: this.posts[this.posts.length - 1].id
diff --git a/src/web/app/mobile/views/pages/followers.vue b/src/web/app/mobile/views/pages/followers.vue
index 1edf4e38ad..b5267bebf4 100644
--- a/src/web/app/mobile/views/pages/followers.vue
+++ b/src/web/app/mobile/views/pages/followers.vue
@@ -7,7 +7,7 @@
 	<mk-users-list
 		v-if="!fetching"
 		:fetch="fetchUsers"
-		:count="user.followers_count"
+		:count="user.followersCount"
 		:you-know-count="user.followers_you_know_count"
 		@loaded="onLoaded"
 	>
@@ -54,7 +54,7 @@ export default Vue.extend({
 		},
 		fetchUsers(iknow, limit, cursor, cb) {
 			(this as any).api('users/followers', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				iknow: iknow,
 				limit: limit,
 				cursor: cursor ? cursor : undefined
diff --git a/src/web/app/mobile/views/pages/following.vue b/src/web/app/mobile/views/pages/following.vue
index 0dd171cce1..d8c31c9f01 100644
--- a/src/web/app/mobile/views/pages/following.vue
+++ b/src/web/app/mobile/views/pages/following.vue
@@ -7,7 +7,7 @@
 	<mk-users-list
 		v-if="!fetching"
 		:fetch="fetchUsers"
-		:count="user.following_count"
+		:count="user.followingCount"
 		:you-know-count="user.following_you_know_count"
 		@loaded="onLoaded"
 	>
@@ -54,7 +54,7 @@ export default Vue.extend({
 		},
 		fetchUsers(iknow, limit, cursor, cb) {
 			(this as any).api('users/following', {
-				user_id: this.user.id,
+				userId: this.user.id,
 				iknow: iknow,
 				limit: limit,
 				cursor: cursor ? cursor : undefined
diff --git a/src/web/app/mobile/views/pages/home.vue b/src/web/app/mobile/views/pages/home.vue
index b110fc4091..be9101aa7f 100644
--- a/src/web/app/mobile/views/pages/home.vue
+++ b/src/web/app/mobile/views/pages/home.vue
@@ -82,8 +82,8 @@ export default Vue.extend({
 		};
 	},
 	created() {
-		if ((this as any).os.i.account.client_settings.mobile_home == null) {
-			Vue.set((this as any).os.i.account.client_settings, 'mobile_home', [{
+		if ((this as any).os.i.account.clientSettings.mobile_home == null) {
+			Vue.set((this as any).os.i.account.clientSettings, 'mobile_home', [{
 				name: 'calendar',
 				id: 'a', data: {}
 			}, {
@@ -105,14 +105,14 @@ export default Vue.extend({
 				name: 'version',
 				id: 'g', data: {}
 			}]);
-			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
+			this.widgets = (this as any).os.i.account.clientSettings.mobile_home;
 			this.saveHome();
 		} else {
-			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
+			this.widgets = (this as any).os.i.account.clientSettings.mobile_home;
 		}
 
-		this.$watch('os.i.account.client_settings', i => {
-			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
+		this.$watch('os.i.account.clientSettings', i => {
+			this.widgets = (this as any).os.i.account.clientSettings.mobile_home;
 		}, {
 			deep: true
 		});
@@ -144,7 +144,7 @@ export default Vue.extend({
 			Progress.done();
 		},
 		onStreamPost(post) {
-			if (document.hidden && post.user_id !== (this as any).os.i.id) {
+			if (document.hidden && post.userId !== (this as any).os.i.id) {
 				this.unreadCount++;
 				document.title = `(${this.unreadCount}) ${getPostSummary(post)}`;
 			}
@@ -157,15 +157,15 @@ export default Vue.extend({
 		},
 		onHomeUpdated(data) {
 			if (data.home) {
-				(this as any).os.i.account.client_settings.mobile_home = data.home;
+				(this as any).os.i.account.clientSettings.mobile_home = data.home;
 				this.widgets = data.home;
 			} else {
-				const w = (this as any).os.i.account.client_settings.mobile_home.find(w => w.id == data.id);
+				const w = (this as any).os.i.account.clientSettings.mobile_home.find(w => w.id == data.id);
 				if (w != null) {
 					w.data = data.data;
 					this.$refs[w.id][0].preventSave = true;
 					this.$refs[w.id][0].props = w.data;
-					this.widgets = (this as any).os.i.account.client_settings.mobile_home;
+					this.widgets = (this as any).os.i.account.clientSettings.mobile_home;
 				}
 			}
 		},
@@ -194,7 +194,7 @@ export default Vue.extend({
 			this.saveHome();
 		},
 		saveHome() {
-			(this as any).os.i.account.client_settings.mobile_home = this.widgets;
+			(this as any).os.i.account.clientSettings.mobile_home = this.widgets;
 			(this as any).api('i/update_mobile_home', {
 				home: this.widgets
 			});
diff --git a/src/web/app/mobile/views/pages/post.vue b/src/web/app/mobile/views/pages/post.vue
index 2ed2ebfcfd..49a4bfd9dc 100644
--- a/src/web/app/mobile/views/pages/post.vue
+++ b/src/web/app/mobile/views/pages/post.vue
@@ -38,7 +38,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('posts/show', {
-				post_id: this.$route.params.post
+				postId: this.$route.params.post
 			}).then(post => {
 				this.post = post;
 				this.fetching = false;
diff --git a/src/web/app/mobile/views/pages/profile-setting.vue b/src/web/app/mobile/views/pages/profile-setting.vue
index 941165c99e..d4bb254877 100644
--- a/src/web/app/mobile/views/pages/profile-setting.vue
+++ b/src/web/app/mobile/views/pages/profile-setting.vue
@@ -69,7 +69,7 @@ export default Vue.extend({
 				this.avatarSaving = true;
 
 				(this as any).api('i/update', {
-					avatar_id: file.id
+					avatarId: file.id
 				}).then(() => {
 					this.avatarSaving = false;
 					alert('%i18n:mobile.tags.mk-profile-setting.avatar-saved%');
@@ -83,7 +83,7 @@ export default Vue.extend({
 				this.bannerSaving = true;
 
 				(this as any).api('i/update', {
-					banner_id: file.id
+					bannerId: file.id
 				}).then(() => {
 					this.bannerSaving = false;
 					alert('%i18n:mobile.tags.mk-profile-setting.banner-saved%');
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index 7ff897e42d..c4d6b67e6c 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -27,15 +27,15 @@
 				</div>
 				<div class="status">
 					<a>
-						<b>{{ user.posts_count | number }}</b>
+						<b>{{ user.postsCount | number }}</b>
 						<i>%i18n:mobile.tags.mk-user.posts%</i>
 					</a>
 					<a :href="`@${acct}/following`">
-						<b>{{ user.following_count | number }}</b>
+						<b>{{ user.followingCount | number }}</b>
 						<i>%i18n:mobile.tags.mk-user.following%</i>
 					</a>
 					<a :href="`@${acct}/followers`">
-						<b>{{ user.followers_count | number }}</b>
+						<b>{{ user.followersCount | number }}</b>
 						<i>%i18n:mobile.tags.mk-user.followers%</i>
 					</a>
 				</div>
diff --git a/src/web/app/mobile/views/pages/user/home.followers-you-know.vue b/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
index 1a2b8f7083..508ab4b4a7 100644
--- a/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
+++ b/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
@@ -27,7 +27,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/followers', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			iknow: true,
 			limit: 30
 		}).then(res => {
diff --git a/src/web/app/mobile/views/pages/user/home.friends.vue b/src/web/app/mobile/views/pages/user/home.friends.vue
index b37f1a2fe8..469781abb9 100644
--- a/src/web/app/mobile/views/pages/user/home.friends.vue
+++ b/src/web/app/mobile/views/pages/user/home.friends.vue
@@ -20,7 +20,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/get_frequently_replied_users', {
-			user_id: this.user.id
+			userId: this.user.id
 		}).then(res => {
 			this.users = res.map(x => x.user);
 			this.fetching = false;
diff --git a/src/web/app/mobile/views/pages/user/home.photos.vue b/src/web/app/mobile/views/pages/user/home.photos.vue
index f12f59a407..94b5af5531 100644
--- a/src/web/app/mobile/views/pages/user/home.photos.vue
+++ b/src/web/app/mobile/views/pages/user/home.photos.vue
@@ -29,7 +29,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/posts', {
-			user_id: this.user.id,
+			userId: this.user.id,
 			with_media: true,
 			limit: 6
 		}).then(posts => {
diff --git a/src/web/app/mobile/views/pages/user/home.posts.vue b/src/web/app/mobile/views/pages/user/home.posts.vue
index 70b20ce943..654f7f63e0 100644
--- a/src/web/app/mobile/views/pages/user/home.posts.vue
+++ b/src/web/app/mobile/views/pages/user/home.posts.vue
@@ -20,7 +20,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		(this as any).api('users/posts', {
-			user_id: this.user.id
+			userId: this.user.id
 		}).then(posts => {
 			this.posts = posts;
 			this.fetching = false;
diff --git a/src/web/app/mobile/views/pages/user/home.vue b/src/web/app/mobile/views/pages/user/home.vue
index e3def61512..1afcd1f5ba 100644
--- a/src/web/app/mobile/views/pages/user/home.vue
+++ b/src/web/app/mobile/views/pages/user/home.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="root home">
-	<mk-post-detail v-if="user.pinned_post" :post="user.pinned_post" :compact="true"/>
+	<mk-post-detail v-if="user.pinnedPost" :post="user.pinnedPost" :compact="true"/>
 	<section class="recent-posts">
 		<h2>%fa:R comments%%i18n:mobile.tags.mk-user-overview.recent-posts%</h2>
 		<div>
@@ -31,7 +31,7 @@
 			<x-followers-you-know :user="user"/>
 		</div>
 	</section>
-	<p v-if="user.host === null">%i18n:mobile.tags.mk-user-overview.last-used-at%: <b><mk-time :time="user.account.last_used_at"/></b></p>
+	<p v-if="user.host === null">%i18n:mobile.tags.mk-user-overview.last-used-at%: <b><mk-time :time="user.account.lastUsedAt"/></b></p>
 </div>
 </template>
 
diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue
index 8557448346..7a809702c5 100644
--- a/src/web/app/mobile/views/pages/welcome.vue
+++ b/src/web/app/mobile/views/pages/welcome.vue
@@ -8,7 +8,7 @@
 			<form @submit.prevent="onSubmit">
 				<input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/>
 				<input v-model="password" type="password" placeholder="パスワード" required/>
-				<input v-if="user && user.account.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/>
+				<input v-if="user && user.account.twoFactorEnabled" v-model="token" type="number" placeholder="トークン" required/>
 				<button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button>
 			</form>
 			<div>
@@ -70,7 +70,7 @@ export default Vue.extend({
 			(this as any).api('signin', {
 				username: this.username,
 				password: this.password,
-				token: this.user && this.user.account.two_factor_enabled ? this.token : undefined
+				token: this.user && this.user.account.twoFactorEnabled ? this.token : undefined
 			}).then(() => {
 				location.reload();
 			}).catch(() => {
diff --git a/src/web/app/stats/tags/index.tag b/src/web/app/stats/tags/index.tag
index 4b167ccbc8..bf08c38c3a 100644
--- a/src/web/app/stats/tags/index.tag
+++ b/src/web/app/stats/tags/index.tag
@@ -57,7 +57,7 @@
 </mk-index>
 
 <mk-posts>
-	<h2>%i18n:stats.posts-count% <b>{ stats.posts_count }</b></h2>
+	<h2>%i18n:stats.posts-count% <b>{ stats.postsCount }</b></h2>
 	<mk-posts-chart v-if="!initializing" data={ data }/>
 	<style lang="stylus" scoped>
 		:scope
diff --git a/src/web/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml
index 5e2307dab4..70d35008c0 100644
--- a/src/web/docs/api/endpoints/posts/create.yaml
+++ b/src/web/docs/api/endpoints/posts/create.yaml
@@ -11,19 +11,19 @@ params:
     desc:
       ja: "投稿の本文"
       en: "The text of your post"
-  - name: "media_ids"
+  - name: "mediaIds"
     type: "id(DriveFile)[]"
     optional: true
     desc:
       ja: "添付するメディア(1~4つ)"
       en: "Media you want to attach (1~4)"
-  - name: "reply_id"
+  - name: "replyId"
     type: "id(Post)"
     optional: true
     desc:
       ja: "返信する投稿"
       en: "The post you want to reply"
-  - name: "repost_id"
+  - name: "repostId"
     type: "id(Post)"
     optional: true
     desc:
diff --git a/src/web/docs/api/entities/drive-file.yaml b/src/web/docs/api/entities/drive-file.yaml
index 2ebbb089ab..02ab0d608e 100644
--- a/src/web/docs/api/entities/drive-file.yaml
+++ b/src/web/docs/api/entities/drive-file.yaml
@@ -11,13 +11,13 @@ props:
     desc:
       ja: "ファイルID"
       en: "The ID of this file"
-  - name: "created_at"
+  - name: "createdAt"
     type: "date"
     optional: false
     desc:
       ja: "アップロード日時"
       en: "The upload date of this file"
-  - name: "user_id"
+  - name: "userId"
     type: "id(User)"
     optional: false
     desc:
@@ -59,7 +59,7 @@ props:
     desc:
       ja: "ファイルのURL"
       en: "The URL of this file"
-  - name: "folder_id"
+  - name: "folderId"
     type: "id(DriveFolder)"
     optional: true
     desc:
diff --git a/src/web/docs/api/entities/post.yaml b/src/web/docs/api/entities/post.yaml
index f780263144..8a616f088b 100644
--- a/src/web/docs/api/entities/post.yaml
+++ b/src/web/docs/api/entities/post.yaml
@@ -11,13 +11,13 @@ props:
     desc:
       ja: "投稿ID"
       en: "The ID of this post"
-  - name: "created_at"
+  - name: "createdAt"
     type: "date"
     optional: false
     desc:
       ja: "投稿日時"
       en: "The posted date of this post"
-  - name: "via_mobile"
+  - name: "viaMobile"
     type: "boolean"
     optional: true
     desc:
@@ -29,7 +29,7 @@ props:
     desc:
       ja: "投稿の本文"
       en: "The text of this post"
-  - name: "media_ids"
+  - name: "mediaIds"
     type: "id(DriveFile)[]"
     optional: true
     desc:
@@ -41,7 +41,7 @@ props:
     desc:
       ja: "添付されているメディア"
       en: "The attached media"
-  - name: "user_id"
+  - name: "userId"
     type: "id(User)"
     optional: false
     desc:
@@ -64,7 +64,7 @@ props:
     optional: false
     desc:
       ja: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト"
-  - name: "reply_id"
+  - name: "replyId"
     type: "id(Post)"
     optional: true
     desc:
@@ -76,7 +76,7 @@ props:
     desc:
       ja: "返信した投稿"
       en: "The replyed post"
-  - name: "repost_id"
+  - name: "repostId"
     type: "id(Post)"
     optional: true
     desc:
diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml
index a451a40807..60f2c86084 100644
--- a/src/web/docs/api/entities/user.yaml
+++ b/src/web/docs/api/entities/user.yaml
@@ -11,7 +11,7 @@ props:
     desc:
       ja: "ユーザーID"
       en: "The ID of this user"
-  - name: "created_at"
+  - name: "createdAt"
     type: "date"
     optional: false
     desc:
@@ -29,7 +29,7 @@ props:
     desc:
       ja: "アカウントの説明(自己紹介)"
       en: "The description of this user"
-  - name: "avatar_id"
+  - name: "avatarId"
     type: "id(DriveFile)"
     optional: true
     desc:
@@ -41,7 +41,7 @@ props:
     desc:
       ja: "アバターのURL"
       en: "The URL of the avatar of this user"
-  - name: "banner_id"
+  - name: "bannerId"
     type: "id(DriveFile)"
     optional: true
     desc:
@@ -53,13 +53,13 @@ props:
     desc:
       ja: "バナーのURL"
       en: "The URL of the banner of this user"
-  - name: "followers_count"
+  - name: "followersCount"
     type: "number"
     optional: false
     desc:
       ja: "フォロワーの数"
       en: "The number of the followers for this user"
-  - name: "following_count"
+  - name: "followingCount"
     type: "number"
     optional: false
     desc:
@@ -81,25 +81,25 @@ props:
     desc:
       ja: "自分がこのユーザーをミュートしているか"
       en: "Whether you muted this user"
-  - name: "posts_count"
+  - name: "postsCount"
     type: "number"
     optional: false
     desc:
       ja: "投稿の数"
       en: "The number of the posts of this user"
-  - name: "pinned_post"
+  - name: "pinnedPost"
     type: "entity(Post)"
     optional: true
     desc:
       ja: "ピン留めされた投稿"
       en: "The pinned post of this user"
-  - name: "pinned_post_id"
+  - name: "pinnedPostId"
     type: "id(Post)"
     optional: true
     desc:
       ja: "ピン留めされた投稿のID"
       en: "The ID of the pinned post of this user"
-  - name: "drive_capacity"
+  - name: "driveCapacity"
     type: "number"
     optional: false
     desc:
@@ -119,13 +119,13 @@ props:
       en: "The account of this user on this server"
     defName: "account"
     def:
-      - name: "last_used_at"
+      - name: "lastUsedAt"
         type: "date"
         optional: false
         desc:
           ja: "最終利用日時"
           en: "The last used date of this user"
-      - name: "is_bot"
+      - name: "isBot"
         type: "boolean"
         optional: true
         desc:
@@ -139,13 +139,13 @@ props:
           en: "The info of the connected twitter account of this user"
         defName: "twitter"
         def:
-          - name: "user_id"
+          - name: "userId"
             type: "string"
             optional: false
             desc:
               ja: "ユーザーID"
               en: "The user ID"
-          - name: "screen_name"
+          - name: "screenName"
             type: "string"
             optional: false
             desc:

From 1acc30822d869fcd4edf70fd8a8dca72f21c8730 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:46:11 +0900
Subject: [PATCH 21/43] wip

---
 src/api/bot/core.ts                           |  4 +--
 src/api/bot/interfaces/line.ts                |  2 +-
 src/api/endpoints.ts                          |  2 +-
 src/api/endpoints/app/create.ts               | 10 +++----
 src/api/endpoints/auth/session/generate.ts    |  8 +++---
 src/api/endpoints/auth/session/userkey.ts     |  8 +++---
 src/api/endpoints/channels.ts                 | 16 +++++------
 src/api/endpoints/channels/posts.ts           | 16 +++++------
 src/api/endpoints/drive/files.ts              | 16 +++++------
 src/api/endpoints/drive/folders.ts            | 16 +++++------
 src/api/endpoints/drive/stream.ts             | 16 +++++------
 src/api/endpoints/i/change_password.ts        | 12 ++++----
 src/api/endpoints/i/notifications.ts          | 22 +++++++--------
 src/api/endpoints/i/signin_history.ts         | 16 +++++------
 src/api/endpoints/i/update.ts                 |  8 +++---
 src/api/endpoints/messaging/messages.ts       | 22 +++++++--------
 src/api/endpoints/othello/games.ts            | 16 +++++------
 src/api/endpoints/posts.ts                    | 16 +++++------
 src/api/endpoints/posts/create.ts             |  2 +-
 src/api/endpoints/posts/mentions.ts           | 16 +++++------
 src/api/endpoints/posts/polls/vote.ts         |  2 +-
 src/api/endpoints/posts/reactions/create.ts   |  2 +-
 src/api/endpoints/posts/reposts.ts            | 16 +++++------
 src/api/endpoints/posts/search.ts             | 12 ++++----
 src/api/endpoints/posts/timeline.ts           | 28 +++++++++----------
 src/api/endpoints/users/posts.ts              | 28 +++++++++----------
 src/api/models/user.ts                        |  4 +--
 src/api/private/signup.ts                     |  2 +-
 src/web/app/auth/views/index.vue              |  8 +++---
 .../common/scripts/compose-notification.ts    | 12 ++++----
 .../common/views/components/autocomplete.vue  |  2 +-
 .../components/messaging-room.message.vue     |  2 +-
 .../views/components/messaging-room.vue       |  2 +-
 .../app/common/views/components/messaging.vue |  4 +--
 .../common/views/components/othello.game.vue  |  4 +--
 .../app/common/views/components/othello.vue   | 10 +++----
 .../views/components/welcome-timeline.vue     |  2 +-
 src/web/app/desktop/api/update-avatar.ts      |  2 +-
 src/web/app/desktop/api/update-banner.ts      |  2 +-
 .../views/components/followers-window.vue     |  2 +-
 .../views/components/following-window.vue     |  2 +-
 .../views/components/friends-maker.vue        |  2 +-
 .../app/desktop/views/components/mentions.vue |  2 +-
 .../views/components/notifications.vue        | 16 +++++------
 .../views/components/post-detail.sub.vue      |  2 +-
 .../desktop/views/components/post-detail.vue  |  4 +--
 .../desktop/views/components/post-preview.vue |  2 +-
 .../views/components/posts.post.sub.vue       |  2 +-
 .../desktop/views/components/posts.post.vue   |  4 +--
 .../views/components/settings.password.vue    |  4 +--
 .../views/components/settings.profile.vue     |  2 +-
 .../app/desktop/views/components/settings.vue |  4 +--
 .../app/desktop/views/components/timeline.vue |  4 +--
 .../views/components/ui.header.account.vue    |  2 +-
 .../desktop/views/components/user-preview.vue |  4 +--
 .../views/components/users-list.item.vue      |  2 +-
 .../pages/user/user.followers-you-know.vue    |  2 +-
 .../desktop/views/pages/user/user.friends.vue |  2 +-
 .../desktop/views/pages/user/user.header.vue  | 10 +++----
 .../views/pages/user/user.timeline.vue        |  4 +--
 src/web/app/desktop/views/pages/welcome.vue   |  2 +-
 src/web/app/desktop/views/widgets/profile.vue |  4 +--
 src/web/app/desktop/views/widgets/users.vue   |  2 +-
 src/web/app/dev/views/new-app.vue             |  2 +-
 src/web/app/mobile/views/components/drive.vue |  2 +-
 .../views/components/notification-preview.vue | 14 +++++-----
 .../mobile/views/components/notification.vue  |  8 +++---
 .../mobile/views/components/notifications.vue |  2 +-
 .../views/components/post-detail.sub.vue      |  2 +-
 .../mobile/views/components/post-detail.vue   |  4 +--
 .../mobile/views/components/post-preview.vue  |  2 +-
 .../app/mobile/views/components/post.sub.vue  |  2 +-
 src/web/app/mobile/views/components/post.vue  |  4 +--
 .../app/mobile/views/components/timeline.vue  |  4 +--
 .../app/mobile/views/components/ui.nav.vue    |  2 +-
 .../app/mobile/views/components/user-card.vue |  4 +--
 .../mobile/views/components/user-preview.vue  |  2 +-
 .../mobile/views/components/user-timeline.vue |  2 +-
 src/web/app/mobile/views/pages/followers.vue  |  2 +-
 src/web/app/mobile/views/pages/following.vue  |  2 +-
 .../app/mobile/views/pages/notifications.vue  |  2 +-
 .../mobile/views/pages/profile-setting.vue    |  4 +--
 src/web/app/mobile/views/pages/user.vue       |  4 +--
 .../pages/user/home.followers-you-know.vue    |  2 +-
 src/web/app/mobile/views/pages/welcome.vue    |  2 +-
 src/web/app/mobile/views/widgets/profile.vue  |  4 +--
 src/web/docs/api.ja.pug                       |  4 +--
 .../docs/api/endpoints/posts/timeline.yaml    |  8 +++---
 src/web/docs/api/entities/user.yaml           |  4 +--
 swagger.js                                    |  4 +--
 90 files changed, 286 insertions(+), 286 deletions(-)

diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts
index 9e699572de..ec7c935f9e 100644
--- a/src/api/bot/core.ts
+++ b/src/api/bot/core.ts
@@ -297,7 +297,7 @@ class TlContext extends Context {
 	private async getTl() {
 		const tl = await require('../endpoints/posts/timeline')({
 			limit: 5,
-			until_id: this.next ? this.next : undefined
+			untilId: this.next ? this.next : undefined
 		}, this.bot.user);
 
 		if (tl.length > 0) {
@@ -349,7 +349,7 @@ class NotificationsContext extends Context {
 	private async getNotifications() {
 		const notifications = await require('../endpoints/i/notifications')({
 			limit: 5,
-			until_id: this.next ? this.next : undefined
+			untilId: this.next ? this.next : undefined
 		}, this.bot.user);
 
 		if (notifications.length > 0) {
diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts
index dc600125c5..296b42a284 100644
--- a/src/api/bot/interfaces/line.ts
+++ b/src/api/bot/interfaces/line.ts
@@ -130,7 +130,7 @@ class LineBot extends BotCore {
 			altText: await super.showUserCommand(q),
 			template: {
 				type: 'buttons',
-				thumbnailImageUrl: `${user.avatar_url}?thumbnail&size=1024`,
+				thumbnailImageUrl: `${user.avatarUrl}?thumbnail&size=1024`,
 				title: `${user.name} (@${acct})`,
 				text: user.description || '(no description)',
 				actions: actions
diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts
index c7100bd036..979d8ac295 100644
--- a/src/api/endpoints.ts
+++ b/src/api/endpoints.ts
@@ -289,7 +289,7 @@ const endpoints: Endpoint[] = [
 		kind: 'notification-write'
 	},
 	{
-		name: 'notifications/mark_as_read_all',
+		name: 'notifications/markAsRead_all',
 		withCredential: true,
 		kind: 'notification-write'
 	},
diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts
index cde4846e0f..713078463d 100644
--- a/src/api/endpoints/app/create.ts
+++ b/src/api/endpoints/app/create.ts
@@ -40,7 +40,7 @@ import App, { isValidNameId, pack } from '../../models/app';
  *           type: string
  *           collectionFormat: csv
  *       -
- *         name: callback_url
+ *         name: callbackUrl
  *         description: URL called back after authentication
  *         in: formData
  *         required: false
@@ -82,10 +82,10 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	const [permission, permissionErr] = $(params.permission).array('string').unique().$;
 	if (permissionErr) return rej('invalid permission param');
 
-	// Get 'callback_url' parameter
+	// Get 'callbackUrl' parameter
 	// TODO: Check it is valid url
-	const [callbackUrl = null, callbackUrlErr] = $(params.callback_url).optional.nullable.string().$;
-	if (callbackUrlErr) return rej('invalid callback_url param');
+	const [callbackUrl = null, callbackUrlErr] = $(params.callbackUrl).optional.nullable.string().$;
+	if (callbackUrlErr) return rej('invalid callbackUrl param');
 
 	// Generate secret
 	const secret = rndstr('a-zA-Z0-9', 32);
@@ -99,7 +99,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 		nameIdLower: nameId.toLowerCase(),
 		description: description,
 		permission: permission,
-		callback_url: callbackUrl,
+		callbackUrl: callbackUrl,
 		secret: secret
 	});
 
diff --git a/src/api/endpoints/auth/session/generate.ts b/src/api/endpoints/auth/session/generate.ts
index 81db188ee5..a087b46d82 100644
--- a/src/api/endpoints/auth/session/generate.ts
+++ b/src/api/endpoints/auth/session/generate.ts
@@ -14,7 +14,7 @@ import config from '../../../../conf';
  *     summary: Generate a session
  *     parameters:
  *       -
- *         name: app_secret
+ *         name: appSecret
  *         description: App Secret
  *         in: formData
  *         required: true
@@ -45,9 +45,9 @@ import config from '../../../../conf';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'app_secret' parameter
-	const [appSecret, appSecretErr] = $(params.app_secret).string().$;
-	if (appSecretErr) return rej('invalid app_secret param');
+	// Get 'appSecret' parameter
+	const [appSecret, appSecretErr] = $(params.appSecret).string().$;
+	if (appSecretErr) return rej('invalid appSecret param');
 
 	// Lookup app
 	const app = await App.findOne({
diff --git a/src/api/endpoints/auth/session/userkey.ts b/src/api/endpoints/auth/session/userkey.ts
index 74f025c8a5..5d9983af67 100644
--- a/src/api/endpoints/auth/session/userkey.ts
+++ b/src/api/endpoints/auth/session/userkey.ts
@@ -14,7 +14,7 @@ import { pack } from '../../../models/user';
  *     summary: Get an access token(userkey)
  *     parameters:
  *       -
- *         name: app_secret
+ *         name: appSecret
  *         description: App Secret
  *         in: formData
  *         required: true
@@ -50,9 +50,9 @@ import { pack } from '../../../models/user';
  * @return {Promise<any>}
  */
 module.exports = (params) => new Promise(async (res, rej) => {
-	// Get 'app_secret' parameter
-	const [appSecret, appSecretErr] = $(params.app_secret).string().$;
-	if (appSecretErr) return rej('invalid app_secret param');
+	// Get 'appSecret' parameter
+	const [appSecret, appSecretErr] = $(params.appSecret).string().$;
+	if (appSecretErr) return rej('invalid appSecret param');
 
 	// Lookup app
 	const app = await App.findOne({
diff --git a/src/api/endpoints/channels.ts b/src/api/endpoints/channels.ts
index b9a7d1b788..a4acc06605 100644
--- a/src/api/endpoints/channels.ts
+++ b/src/api/endpoints/channels.ts
@@ -16,17 +16,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Construct query
diff --git a/src/api/endpoints/channels/posts.ts b/src/api/endpoints/channels/posts.ts
index 7536664051..348dbb108b 100644
--- a/src/api/endpoints/channels/posts.ts
+++ b/src/api/endpoints/channels/posts.ts
@@ -17,17 +17,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 1000, limitErr] = $(params.limit).optional.number().range(1, 1000).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Get 'channelId' parameter
diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts
index 1ce855932b..f982ef62e0 100644
--- a/src/api/endpoints/drive/files.ts
+++ b/src/api/endpoints/drive/files.ts
@@ -17,17 +17,17 @@ module.exports = async (params, user, app) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) throw 'invalid limit param';
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) throw 'invalid since_id param';
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) throw 'invalid sinceId param';
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) throw 'invalid until_id param';
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) throw 'invalid untilId param';
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		throw 'cannot set since_id and until_id';
+		throw 'cannot set sinceId and untilId';
 	}
 
 	// Get 'folderId' parameter
diff --git a/src/api/endpoints/drive/folders.ts b/src/api/endpoints/drive/folders.ts
index c259646352..c314837f72 100644
--- a/src/api/endpoints/drive/folders.ts
+++ b/src/api/endpoints/drive/folders.ts
@@ -17,17 +17,17 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Get 'folderId' parameter
diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts
index 0f9cea9f1d..71db38f3b3 100644
--- a/src/api/endpoints/drive/stream.ts
+++ b/src/api/endpoints/drive/stream.ts
@@ -16,17 +16,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Get 'type' parameter
diff --git a/src/api/endpoints/i/change_password.ts b/src/api/endpoints/i/change_password.ts
index 88fb36b1fb..e3b0127e7d 100644
--- a/src/api/endpoints/i/change_password.ts
+++ b/src/api/endpoints/i/change_password.ts
@@ -13,13 +13,13 @@ import User from '../../models/user';
  * @return {Promise<any>}
  */
 module.exports = async (params, user) => new Promise(async (res, rej) => {
-	// Get 'current_password' parameter
-	const [currentPassword, currentPasswordErr] = $(params.current_password).string().$;
-	if (currentPasswordErr) return rej('invalid current_password param');
+	// Get 'currentPasword' parameter
+	const [currentPassword, currentPasswordErr] = $(params.currentPasword).string().$;
+	if (currentPasswordErr) return rej('invalid currentPasword param');
 
-	// Get 'new_password' parameter
-	const [newPassword, newPasswordErr] = $(params.new_password).string().$;
-	if (newPasswordErr) return rej('invalid new_password param');
+	// Get 'newPassword' parameter
+	const [newPassword, newPasswordErr] = $(params.newPassword).string().$;
+	if (newPasswordErr) return rej('invalid newPassword param');
 
 	// Compare password
 	const same = await bcrypt.compare(currentPassword, user.account.password);
diff --git a/src/api/endpoints/i/notifications.ts b/src/api/endpoints/i/notifications.ts
index e3447c17ec..7119bf6ea3 100644
--- a/src/api/endpoints/i/notifications.ts
+++ b/src/api/endpoints/i/notifications.ts
@@ -21,9 +21,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		$(params.following).optional.boolean().$;
 	if (followingError) return rej('invalid following param');
 
-	// Get 'mark_as_read' parameter
-	const [markAsRead = true, markAsReadErr] = $(params.mark_as_read).optional.boolean().$;
-	if (markAsReadErr) return rej('invalid mark_as_read param');
+	// Get 'markAsRead' parameter
+	const [markAsRead = true, markAsReadErr] = $(params.markAsRead).optional.boolean().$;
+	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'type' parameter
 	const [type, typeErr] = $(params.type).optional.array('string').unique().$;
@@ -33,17 +33,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	const mute = await Mute.find({
diff --git a/src/api/endpoints/i/signin_history.ts b/src/api/endpoints/i/signin_history.ts
index 5b794d0a4b..a4ba22790c 100644
--- a/src/api/endpoints/i/signin_history.ts
+++ b/src/api/endpoints/i/signin_history.ts
@@ -16,17 +16,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	const query = {
diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts
index 6645751871..45dfddcfe7 100644
--- a/src/api/endpoints/i/update.ts
+++ b/src/api/endpoints/i/update.ts
@@ -51,10 +51,10 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 	if (isBotErr) return rej('invalid isBot param');
 	if (isBot != null) user.account.isBot = isBot;
 
-	// Get 'auto_watch' parameter
-	const [autoWatch, autoWatchErr] = $(params.auto_watch).optional.boolean().$;
-	if (autoWatchErr) return rej('invalid auto_watch param');
-	if (autoWatch != null) user.account.settings.auto_watch = autoWatch;
+	// Get 'autoWatch' parameter
+	const [autoWatch, autoWatchErr] = $(params.autoWatch).optional.boolean().$;
+	if (autoWatchErr) return rej('invalid autoWatch param');
+	if (autoWatch != null) user.account.settings.autoWatch = autoWatch;
 
 	await User.update(user._id, {
 		$set: {
diff --git a/src/api/endpoints/messaging/messages.ts b/src/api/endpoints/messaging/messages.ts
index ba8ca7d1c2..dd80e41d03 100644
--- a/src/api/endpoints/messaging/messages.ts
+++ b/src/api/endpoints/messaging/messages.ts
@@ -32,25 +32,25 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		return rej('user not found');
 	}
 
-	// Get 'mark_as_read' parameter
-	const [markAsRead = true, markAsReadErr] = $(params.mark_as_read).optional.boolean().$;
-	if (markAsReadErr) return rej('invalid mark_as_read param');
+	// Get 'markAsRead' parameter
+	const [markAsRead = true, markAsReadErr] = $(params.markAsRead).optional.boolean().$;
+	if (markAsReadErr) return rej('invalid markAsRead param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	const query = {
diff --git a/src/api/endpoints/othello/games.ts b/src/api/endpoints/othello/games.ts
index 5c71f98828..37fa384189 100644
--- a/src/api/endpoints/othello/games.ts
+++ b/src/api/endpoints/othello/games.ts
@@ -10,17 +10,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	const q: any = my ? {
diff --git a/src/api/endpoints/posts.ts b/src/api/endpoints/posts.ts
index 7e9ff3ad74..bee1de02d4 100644
--- a/src/api/endpoints/posts.ts
+++ b/src/api/endpoints/posts.ts
@@ -35,17 +35,17 @@ module.exports = (params) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Construct query
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 2a3d974fe8..b99d1fbbc1 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -392,7 +392,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 			});
 
 		// この投稿をWatchする
-		if ((user.account as ILocalAccount).settings.auto_watch !== false) {
+		if ((user.account as ILocalAccount).settings.autoWatch !== false) {
 			watch(user._id, reply);
 		}
 
diff --git a/src/api/endpoints/posts/mentions.ts b/src/api/endpoints/posts/mentions.ts
index da90583bbd..1b342e8de9 100644
--- a/src/api/endpoints/posts/mentions.ts
+++ b/src/api/endpoints/posts/mentions.ts
@@ -23,17 +23,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Construct query
diff --git a/src/api/endpoints/posts/polls/vote.ts b/src/api/endpoints/posts/polls/vote.ts
index e87474ae6e..734a3a3c45 100644
--- a/src/api/endpoints/posts/polls/vote.ts
+++ b/src/api/endpoints/posts/polls/vote.ts
@@ -100,7 +100,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		});
 
 	// この投稿をWatchする
-	if (user.account.settings.auto_watch !== false) {
+	if (user.account.settings.autoWatch !== false) {
 		watch(user._id, post);
 	}
 });
diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts
index 7031d28e56..6f75a923cd 100644
--- a/src/api/endpoints/posts/reactions/create.ts
+++ b/src/api/endpoints/posts/reactions/create.ts
@@ -116,7 +116,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		});
 
 	// この投稿をWatchする
-	if (user.account.settings.auto_watch !== false) {
+	if (user.account.settings.autoWatch !== false) {
 		watch(user._id, post);
 	}
 });
diff --git a/src/api/endpoints/posts/reposts.ts b/src/api/endpoints/posts/reposts.ts
index c1645117f0..51af41f523 100644
--- a/src/api/endpoints/posts/reposts.ts
+++ b/src/api/endpoints/posts/reposts.ts
@@ -20,17 +20,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Check if both of since_id and until_id is specified
+	// Check if both of sinceId and untilId is specified
 	if (sinceId && untilId) {
-		return rej('cannot set since_id and until_id');
+		return rej('cannot set sinceId and untilId');
 	}
 
 	// Lookup post
diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts
index e7906c95c8..f90b9aa0dd 100644
--- a/src/api/endpoints/posts/search.ts
+++ b/src/api/endpoints/posts/search.ts
@@ -61,13 +61,13 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [poll = null, pollErr] = $(params.poll).optional.nullable.boolean().$;
 	if (pollErr) return rej('invalid poll param');
 
-	// Get 'since_date' parameter
-	const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$;
-	if (sinceDateErr) throw 'invalid since_date param';
+	// Get 'sinceDate' parameter
+	const [sinceDate, sinceDateErr] = $(params.sinceDate).optional.number().$;
+	if (sinceDateErr) throw 'invalid sinceDate param';
 
-	// Get 'until_date' parameter
-	const [untilDate, untilDateErr] = $(params.until_date).optional.number().$;
-	if (untilDateErr) throw 'invalid until_date param';
+	// Get 'untilDate' parameter
+	const [untilDate, untilDateErr] = $(params.untilDate).optional.number().$;
+	if (untilDateErr) throw 'invalid untilDate param';
 
 	// Get 'offset' parameter
 	const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$;
diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts
index c7cb8032e3..a3e915f16a 100644
--- a/src/api/endpoints/posts/timeline.ts
+++ b/src/api/endpoints/posts/timeline.ts
@@ -22,25 +22,25 @@ module.exports = async (params, user, app) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) throw 'invalid limit param';
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) throw 'invalid since_id param';
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) throw 'invalid sinceId param';
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) throw 'invalid until_id param';
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) throw 'invalid untilId param';
 
-	// Get 'since_date' parameter
-	const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$;
-	if (sinceDateErr) throw 'invalid since_date param';
+	// Get 'sinceDate' parameter
+	const [sinceDate, sinceDateErr] = $(params.sinceDate).optional.number().$;
+	if (sinceDateErr) throw 'invalid sinceDate param';
 
-	// Get 'until_date' parameter
-	const [untilDate, untilDateErr] = $(params.until_date).optional.number().$;
-	if (untilDateErr) throw 'invalid until_date param';
+	// Get 'untilDate' parameter
+	const [untilDate, untilDateErr] = $(params.untilDate).optional.number().$;
+	if (untilDateErr) throw 'invalid untilDate param';
 
-	// Check if only one of since_id, until_id, since_date, until_date specified
+	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
 	if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) {
-		throw 'only one of since_id, until_id, since_date, until_date can be specified';
+		throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
 	}
 
 	const { followingIds, watchingChannelIds, mutedUserIds } = await rap({
diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts
index f08be91c4d..9ece429b60 100644
--- a/src/api/endpoints/users/posts.ts
+++ b/src/api/endpoints/users/posts.ts
@@ -46,25 +46,25 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
 	if (limitErr) return rej('invalid limit param');
 
-	// Get 'since_id' parameter
-	const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
-	if (sinceIdErr) return rej('invalid since_id param');
+	// Get 'sinceId' parameter
+	const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+	if (sinceIdErr) return rej('invalid sinceId param');
 
-	// Get 'until_id' parameter
-	const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
-	if (untilIdErr) return rej('invalid until_id param');
+	// Get 'untilId' parameter
+	const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+	if (untilIdErr) return rej('invalid untilId param');
 
-	// Get 'since_date' parameter
-	const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$;
-	if (sinceDateErr) throw 'invalid since_date param';
+	// Get 'sinceDate' parameter
+	const [sinceDate, sinceDateErr] = $(params.sinceDate).optional.number().$;
+	if (sinceDateErr) throw 'invalid sinceDate param';
 
-	// Get 'until_date' parameter
-	const [untilDate, untilDateErr] = $(params.until_date).optional.number().$;
-	if (untilDateErr) throw 'invalid until_date param';
+	// Get 'untilDate' parameter
+	const [untilDate, untilDateErr] = $(params.untilDate).optional.number().$;
+	if (untilDateErr) throw 'invalid untilDate param';
 
-	// Check if only one of since_id, until_id, since_date, until_date specified
+	// Check if only one of sinceId, untilId, sinceDate, untilDate specified
 	if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) {
-		throw 'only one of since_id, until_id, since_date, until_date can be specified';
+		throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
 	}
 
 	const q = userId !== undefined
diff --git a/src/api/models/user.ts b/src/api/models/user.ts
index 8c68b06dfa..9ee413e0d8 100644
--- a/src/api/models/user.ts
+++ b/src/api/models/user.ts
@@ -195,11 +195,11 @@ export const pack = (
 		}
 	}
 
-	_user.avatar_url = _user.avatarId != null
+	_user.avatarUrl = _user.avatarId != null
 		? `${config.drive_url}/${_user.avatarId}`
 		: `${config.drive_url}/default-avatar.jpg`;
 
-	_user.banner_url = _user.bannerId != null
+	_user.bannerUrl = _user.bannerId != null
 		? `${config.drive_url}/${_user.bannerId}`
 		: null;
 
diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts
index 1304ccb54c..9178c0eb89 100644
--- a/src/api/private/signup.ts
+++ b/src/api/private/signup.ts
@@ -137,7 +137,7 @@ export default async (req: express.Request, res: express.Response) => {
 				weight: null
 			},
 			settings: {
-				auto_watch: true
+				autoWatch: true
 			},
 			clientSettings: {
 				home: homeData
diff --git a/src/web/app/auth/views/index.vue b/src/web/app/auth/views/index.vue
index 17e5cc6108..690cc4f28e 100644
--- a/src/web/app/auth/views/index.vue
+++ b/src/web/app/auth/views/index.vue
@@ -15,8 +15,8 @@
 		</div>
 		<div class="accepted" v-if="state == 'accepted'">
 			<h1>{{ session.app.is_authorized ? 'このアプリは既に連携済みです' : 'アプリケーションの連携を許可しました'}}</h1>
-			<p v-if="session.app.callback_url">アプリケーションに戻っています<mk-ellipsis/></p>
-			<p v-if="!session.app.callback_url">アプリケーションに戻って、やっていってください。</p>
+			<p v-if="session.app.callbackUrl">アプリケーションに戻っています<mk-ellipsis/></p>
+			<p v-if="!session.app.callbackUrl">アプリケーションに戻って、やっていってください。</p>
 		</div>
 		<div class="error" v-if="state == 'fetch-session-error'">
 			<p>セッションが存在しません。</p>
@@ -77,8 +77,8 @@ export default Vue.extend({
 	methods: {
 		accepted() {
 			this.state = 'accepted';
-			if (this.session.app.callback_url) {
-				location.href = this.session.app.callback_url + '?token=' + this.session.token;
+			if (this.session.app.callbackUrl) {
+				location.href = this.session.app.callbackUrl + '?token=' + this.session.token;
 			}
 		}
 	}
diff --git a/src/web/app/common/scripts/compose-notification.ts b/src/web/app/common/scripts/compose-notification.ts
index e1dbd3bc13..273579cbc6 100644
--- a/src/web/app/common/scripts/compose-notification.ts
+++ b/src/web/app/common/scripts/compose-notification.ts
@@ -23,42 +23,42 @@ export default function(type, data): Notification {
 			return {
 				title: `${data.user.name}さんから:`,
 				body: getPostSummary(data),
-				icon: data.user.avatar_url + '?thumbnail&size=64'
+				icon: data.user.avatarUrl + '?thumbnail&size=64'
 			};
 
 		case 'reply':
 			return {
 				title: `${data.user.name}さんから返信:`,
 				body: getPostSummary(data),
-				icon: data.user.avatar_url + '?thumbnail&size=64'
+				icon: data.user.avatarUrl + '?thumbnail&size=64'
 			};
 
 		case 'quote':
 			return {
 				title: `${data.user.name}さんが引用:`,
 				body: getPostSummary(data),
-				icon: data.user.avatar_url + '?thumbnail&size=64'
+				icon: data.user.avatarUrl + '?thumbnail&size=64'
 			};
 
 		case 'reaction':
 			return {
 				title: `${data.user.name}: ${getReactionEmoji(data.reaction)}:`,
 				body: getPostSummary(data.post),
-				icon: data.user.avatar_url + '?thumbnail&size=64'
+				icon: data.user.avatarUrl + '?thumbnail&size=64'
 			};
 
 		case 'unread_messaging_message':
 			return {
 				title: `${data.user.name}さんからメッセージ:`,
 				body: data.text, // TODO: getMessagingMessageSummary(data),
-				icon: data.user.avatar_url + '?thumbnail&size=64'
+				icon: data.user.avatarUrl + '?thumbnail&size=64'
 			};
 
 		case 'othello_invited':
 			return {
 				title: '対局への招待があります',
 				body: `${data.parent.name}さんから`,
-				icon: data.parent.avatar_url + '?thumbnail&size=64'
+				icon: data.parent.avatarUrl + '?thumbnail&size=64'
 			};
 
 		default:
diff --git a/src/web/app/common/views/components/autocomplete.vue b/src/web/app/common/views/components/autocomplete.vue
index 8afa291e3c..79bd2ba023 100644
--- a/src/web/app/common/views/components/autocomplete.vue
+++ b/src/web/app/common/views/components/autocomplete.vue
@@ -2,7 +2,7 @@
 <div class="mk-autocomplete" @contextmenu.prevent="() => {}">
 	<ol class="users" ref="suggests" v-if="users.length > 0">
 		<li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1">
-			<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=32`" alt=""/>
+			<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=32`" alt=""/>
 			<span class="name">{{ user.name }}</span>
 			<span class="username">@{{ getAcct(user) }}</span>
 		</li>
diff --git a/src/web/app/common/views/components/messaging-room.message.vue b/src/web/app/common/views/components/messaging-room.message.vue
index d21cce1a0a..8d35b50391 100644
--- a/src/web/app/common/views/components/messaging-room.message.vue
+++ b/src/web/app/common/views/components/messaging-room.message.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="message" :data-is-me="isMe">
 	<router-link class="avatar-anchor" :to="`/@${acct}`" :title="acct" target="_blank">
-		<img class="avatar" :src="`${message.user.avatar_url}?thumbnail&size=80`" alt=""/>
+		<img class="avatar" :src="`${message.user.avatarUrl}?thumbnail&size=80`" alt=""/>
 	</router-link>
 	<div class="content">
 		<div class="balloon" :data-no-text="message.text == null">
diff --git a/src/web/app/common/views/components/messaging-room.vue b/src/web/app/common/views/components/messaging-room.vue
index 36c53fd3fe..d30c64d74a 100644
--- a/src/web/app/common/views/components/messaging-room.vue
+++ b/src/web/app/common/views/components/messaging-room.vue
@@ -125,7 +125,7 @@ export default Vue.extend({
 				(this as any).api('messaging/messages', {
 					userId: this.user.id,
 					limit: max + 1,
-					until_id: this.existMoreMessages ? this.messages[0].id : undefined
+					untilId: this.existMoreMessages ? this.messages[0].id : undefined
 				}).then(messages => {
 					if (messages.length == max + 1) {
 						this.existMoreMessages = true;
diff --git a/src/web/app/common/views/components/messaging.vue b/src/web/app/common/views/components/messaging.vue
index 0272c67073..8317c3738a 100644
--- a/src/web/app/common/views/components/messaging.vue
+++ b/src/web/app/common/views/components/messaging.vue
@@ -13,7 +13,7 @@
 					@click="navigate(user)"
 					tabindex="-1"
 				>
-					<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=32`" alt=""/>
+					<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=32`" alt=""/>
 					<span class="name">{{ user.name }}</span>
 					<span class="username">@{{ getAcct(user) }}</span>
 				</li>
@@ -31,7 +31,7 @@
 				:key="message.id"
 			>
 				<div>
-					<img class="avatar" :src="`${isMe(message) ? message.recipient.avatar_url : message.user.avatar_url}?thumbnail&size=64`" alt=""/>
+					<img class="avatar" :src="`${isMe(message) ? message.recipient.avatarUrl : message.user.avatarUrl}?thumbnail&size=64`" alt=""/>
 					<header>
 						<span class="name">{{ isMe(message) ? message.recipient.name : message.user.name }}</span>
 						<span class="username">@{{ getAcct(isMe(message) ? message.recipient : message.user) }}</span>
diff --git a/src/web/app/common/views/components/othello.game.vue b/src/web/app/common/views/components/othello.game.vue
index 8150fe07f0..f08742ad10 100644
--- a/src/web/app/common/views/components/othello.game.vue
+++ b/src/web/app/common/views/components/othello.game.vue
@@ -19,8 +19,8 @@
 			@click="set(i)"
 			:title="'[' + (o.transformPosToXy(i)[0] + 1) + ', ' + (o.transformPosToXy(i)[1] + 1) + '] (' + i + ')'"
 		>
-			<img v-if="stone === true" :src="`${blackUser.avatar_url}?thumbnail&size=128`" alt="">
-			<img v-if="stone === false" :src="`${whiteUser.avatar_url}?thumbnail&size=128`" alt="">
+			<img v-if="stone === true" :src="`${blackUser.avatarUrl}?thumbnail&size=128`" alt="">
+			<img v-if="stone === false" :src="`${whiteUser.avatarUrl}?thumbnail&size=128`" alt="">
 		</div>
 	</div>
 
diff --git a/src/web/app/common/views/components/othello.vue b/src/web/app/common/views/components/othello.vue
index 7bdb471005..7737d74ded 100644
--- a/src/web/app/common/views/components/othello.vue
+++ b/src/web/app/common/views/components/othello.vue
@@ -31,7 +31,7 @@
 		<section v-if="invitations.length > 0">
 			<h2>対局の招待があります!:</h2>
 			<div class="invitation" v-for="i in invitations" tabindex="-1" @click="accept(i)">
-				<img :src="`${i.parent.avatar_url}?thumbnail&size=32`" alt="">
+				<img :src="`${i.parent.avatarUrl}?thumbnail&size=32`" alt="">
 				<span class="name"><b>{{ i.parent.name }}</b></span>
 				<span class="username">@{{ i.parent.username }}</span>
 				<mk-time :time="i.createdAt"/>
@@ -40,8 +40,8 @@
 		<section v-if="myGames.length > 0">
 			<h2>自分の対局</h2>
 			<a class="game" v-for="g in myGames" tabindex="-1" @click.prevent="go(g)" :href="`/othello/${g.id}`">
-				<img :src="`${g.user1.avatar_url}?thumbnail&size=32`" alt="">
-				<img :src="`${g.user2.avatar_url}?thumbnail&size=32`" alt="">
+				<img :src="`${g.user1.avatarUrl}?thumbnail&size=32`" alt="">
+				<img :src="`${g.user2.avatarUrl}?thumbnail&size=32`" alt="">
 				<span><b>{{ g.user1.name }}</b> vs <b>{{ g.user2.name }}</b></span>
 				<span class="state">{{ g.isEnded ? '終了' : '進行中' }}</span>
 			</a>
@@ -49,8 +49,8 @@
 		<section v-if="games.length > 0">
 			<h2>みんなの対局</h2>
 			<a class="game" v-for="g in games" tabindex="-1" @click.prevent="go(g)" :href="`/othello/${g.id}`">
-				<img :src="`${g.user1.avatar_url}?thumbnail&size=32`" alt="">
-				<img :src="`${g.user2.avatar_url}?thumbnail&size=32`" alt="">
+				<img :src="`${g.user1.avatarUrl}?thumbnail&size=32`" alt="">
+				<img :src="`${g.user2.avatarUrl}?thumbnail&size=32`" alt="">
 				<span><b>{{ g.user1.name }}</b> vs <b>{{ g.user2.name }}</b></span>
 				<span class="state">{{ g.isEnded ? '終了' : '進行中' }}</span>
 			</a>
diff --git a/src/web/app/common/views/components/welcome-timeline.vue b/src/web/app/common/views/components/welcome-timeline.vue
index c61cae0f76..8f6199732a 100644
--- a/src/web/app/common/views/components/welcome-timeline.vue
+++ b/src/web/app/common/views/components/welcome-timeline.vue
@@ -2,7 +2,7 @@
 <div class="mk-welcome-timeline">
 	<div v-for="post in posts">
 		<router-link class="avatar-anchor" :to="`/@${getAcct(post.user)}`" v-user-preview="post.user.id">
-			<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=96`" alt="avatar"/>
+			<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 		</router-link>
 		<div class="body">
 			<header>
diff --git a/src/web/app/desktop/api/update-avatar.ts b/src/web/app/desktop/api/update-avatar.ts
index 445ef7d745..36a2ffe914 100644
--- a/src/web/app/desktop/api/update-avatar.ts
+++ b/src/web/app/desktop/api/update-avatar.ts
@@ -71,7 +71,7 @@ export default (os: OS) => (cb, file = null) => {
 			avatarId: file.id
 		}).then(i => {
 			os.i.avatarId = i.avatarId;
-			os.i.avatar_url = i.avatar_url;
+			os.i.avatarUrl = i.avatarUrl;
 
 			os.apis.dialog({
 				title: '%fa:info-circle%アバターを更新しました',
diff --git a/src/web/app/desktop/api/update-banner.ts b/src/web/app/desktop/api/update-banner.ts
index 002efce8ce..e66dbf016b 100644
--- a/src/web/app/desktop/api/update-banner.ts
+++ b/src/web/app/desktop/api/update-banner.ts
@@ -71,7 +71,7 @@ export default (os: OS) => (cb, file = null) => {
 			bannerId: file.id
 		}).then(i => {
 			os.i.bannerId = i.bannerId;
-			os.i.banner_url = i.banner_url;
+			os.i.bannerUrl = i.bannerUrl;
 
 			os.apis.dialog({
 				title: '%fa:info-circle%バナーを更新しました',
diff --git a/src/web/app/desktop/views/components/followers-window.vue b/src/web/app/desktop/views/components/followers-window.vue
index d41d356f9b..623971fa33 100644
--- a/src/web/app/desktop/views/components/followers-window.vue
+++ b/src/web/app/desktop/views/components/followers-window.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-window width="400px" height="550px" @closed="$destroy">
 	<span slot="header" :class="$style.header">
-		<img :src="`${user.avatar_url}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロワー
+		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロワー
 	</span>
 	<mk-followers :user="user"/>
 </mk-window>
diff --git a/src/web/app/desktop/views/components/following-window.vue b/src/web/app/desktop/views/components/following-window.vue
index c516b3b17b..612847b386 100644
--- a/src/web/app/desktop/views/components/following-window.vue
+++ b/src/web/app/desktop/views/components/following-window.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-window width="400px" height="550px" @closed="$destroy">
 	<span slot="header" :class="$style.header">
-		<img :src="`${user.avatar_url}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロー
+		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロー
 	</span>
 	<mk-following :user="user"/>
 </mk-window>
diff --git a/src/web/app/desktop/views/components/friends-maker.vue b/src/web/app/desktop/views/components/friends-maker.vue
index eed15e0773..fd9914b152 100644
--- a/src/web/app/desktop/views/components/friends-maker.vue
+++ b/src/web/app/desktop/views/components/friends-maker.vue
@@ -4,7 +4,7 @@
 	<div class="users" v-if="!fetching && users.length > 0">
 		<div class="user" v-for="user in users" :key="user.id">
 			<router-link class="avatar-anchor" :to="`/@${getAcct(user)}`">
-				<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=42`" alt="" v-user-preview="user.id"/>
+				<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="user.id"/>
 			</router-link>
 			<div class="body">
 				<router-link class="name" :to="`/@${getAcct(user)}`" v-user-preview="user.id">{{ user.name }}</router-link>
diff --git a/src/web/app/desktop/views/components/mentions.vue b/src/web/app/desktop/views/components/mentions.vue
index 47066e813f..90a92495b7 100644
--- a/src/web/app/desktop/views/components/mentions.vue
+++ b/src/web/app/desktop/views/components/mentions.vue
@@ -70,7 +70,7 @@ export default Vue.extend({
 			this.moreFetching = true;
 			(this as any).api('posts/mentions', {
 				following: this.mode == 'following',
-				until_id: this.posts[this.posts.length - 1].id
+				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
 				this.posts = this.posts.concat(posts);
 				this.moreFetching = false;
diff --git a/src/web/app/desktop/views/components/notifications.vue b/src/web/app/desktop/views/components/notifications.vue
index 62593cf97e..5e6db08c12 100644
--- a/src/web/app/desktop/views/components/notifications.vue
+++ b/src/web/app/desktop/views/components/notifications.vue
@@ -6,7 +6,7 @@
 				<mk-time :time="notification.createdAt"/>
 				<template v-if="notification.type == 'reaction'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.user)}`" v-user-preview="notification.user.id">
-						<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>
@@ -20,7 +20,7 @@
 				</template>
 				<template v-if="notification.type == 'repost'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
-						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:retweet%
@@ -33,7 +33,7 @@
 				</template>
 				<template v-if="notification.type == 'quote'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
-						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:quote-left%
@@ -44,7 +44,7 @@
 				</template>
 				<template v-if="notification.type == 'follow'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.user)}`" v-user-preview="notification.user.id">
-						<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:user-plus%
@@ -54,7 +54,7 @@
 				</template>
 				<template v-if="notification.type == 'reply'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
-						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:reply%
@@ -65,7 +65,7 @@
 				</template>
 				<template v-if="notification.type == 'mention'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.post.user)}`" v-user-preview="notification.post.userId">
-						<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:at%
@@ -76,7 +76,7 @@
 				</template>
 				<template v-if="notification.type == 'poll_vote'">
 					<router-link class="avatar-anchor" :to="`/@${getAcct(notification.user)}`" v-user-preview="notification.user.id">
-						<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=48`" alt="avatar"/>
+						<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 					</router-link>
 					<div class="text">
 						<p>%fa:chart-pie%<a :href="`/@${getAcct(notification.user)}`" v-user-preview="notification.user.id">{{ notification.user.name }}</a></p>
@@ -161,7 +161,7 @@ export default Vue.extend({
 
 			(this as any).api('i/notifications', {
 				limit: max + 1,
-				until_id: this.notifications[this.notifications.length - 1].id
+				untilId: this.notifications[this.notifications.length - 1].id
 			}).then(notifications => {
 				if (notifications.length == max + 1) {
 					this.moreNotifications = true;
diff --git a/src/web/app/desktop/views/components/post-detail.sub.vue b/src/web/app/desktop/views/components/post-detail.sub.vue
index 7453a8bfcf..35377e7c24 100644
--- a/src/web/app/desktop/views/components/post-detail.sub.vue
+++ b/src/web/app/desktop/views/components/post-detail.sub.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="sub" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index 1ab751aaf8..611660f523 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -19,7 +19,7 @@
 	<div class="repost" v-if="isRepost">
 		<p>
 			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.userId">
-				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=32`" alt="avatar"/>
+				<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
 			<router-link class="name" :href="`/@${acct}`">{{ post.user.name }}</router-link>
@@ -28,7 +28,7 @@
 	</div>
 	<article>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${p.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
+			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
 		</router-link>
 		<header>
 			<router-link class="name" :to="`/@${acct}`" v-user-preview="p.user.id">{{ p.user.name }}</router-link>
diff --git a/src/web/app/desktop/views/components/post-preview.vue b/src/web/app/desktop/views/components/post-preview.vue
index 450632656d..0ac3223be2 100644
--- a/src/web/app/desktop/views/components/post-preview.vue
+++ b/src/web/app/desktop/views/components/post-preview.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-post-preview" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/desktop/views/components/posts.post.sub.vue b/src/web/app/desktop/views/components/posts.post.sub.vue
index 7d2695d6b9..65d3017d3d 100644
--- a/src/web/app/desktop/views/components/posts.post.sub.vue
+++ b/src/web/app/desktop/views/components/posts.post.sub.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="sub" :title="title">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="post.userId"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue
index 185a621aae..e6dff2ccda 100644
--- a/src/web/app/desktop/views/components/posts.post.vue
+++ b/src/web/app/desktop/views/components/posts.post.vue
@@ -6,7 +6,7 @@
 	<div class="repost" v-if="isRepost">
 		<p>
 			<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="post.userId">
-				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=32`" alt="avatar"/>
+				<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
 			<span>{{ '%i18n:desktop.tags.mk-timeline-post.reposted-by%'.substr(0, '%i18n:desktop.tags.mk-timeline-post.reposted-by%'.indexOf('{')) }}</span>
@@ -17,7 +17,7 @@
 	</div>
 	<article>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${p.user.avatar_url}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
+			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
 		</router-link>
 		<div class="main">
 			<header>
diff --git a/src/web/app/desktop/views/components/settings.password.vue b/src/web/app/desktop/views/components/settings.password.vue
index be3f0370d6..f883b54065 100644
--- a/src/web/app/desktop/views/components/settings.password.vue
+++ b/src/web/app/desktop/views/components/settings.password.vue
@@ -33,8 +33,8 @@ export default Vue.extend({
 							return;
 						}
 						(this as any).api('i/change_password', {
-							current_password: currentPassword,
-							new_password: newPassword
+							currentPasword: currentPassword,
+							newPassword: newPassword
 						}).then(() => {
 							(this as any).apis.notify('%i18n:desktop.tags.mk-password-setting.changed%');
 						});
diff --git a/src/web/app/desktop/views/components/settings.profile.vue b/src/web/app/desktop/views/components/settings.profile.vue
index f34d8ff00d..ba86286f87 100644
--- a/src/web/app/desktop/views/components/settings.profile.vue
+++ b/src/web/app/desktop/views/components/settings.profile.vue
@@ -2,7 +2,7 @@
 <div class="profile">
 	<label class="avatar ui from group">
 		<p>%i18n:desktop.tags.mk-profile-setting.avatar%</p>
-		<img class="avatar" :src="`${os.i.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<button class="ui" @click="updateAvatar">%i18n:desktop.tags.mk-profile-setting.choice-avatar%</button>
 	</label>
 	<label class="ui from group">
diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue
index cf75e52be2..fd82c171c1 100644
--- a/src/web/app/desktop/views/components/settings.vue
+++ b/src/web/app/desktop/views/components/settings.vue
@@ -86,7 +86,7 @@
 
 		<section class="notification" v-show="page == 'notification'">
 			<h1>通知</h1>
-			<mk-switch v-model="os.i.account.settings.auto_watch" @change="onChangeAutoWatch" text="投稿の自動ウォッチ">
+			<mk-switch v-model="os.i.account.settings.autoWatch" @change="onChangeAutoWatch" text="投稿の自動ウォッチ">
 				<span>リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。</span>
 			</mk-switch>
 		</section>
@@ -283,7 +283,7 @@ export default Vue.extend({
 		},
 		onChangeAutoWatch(v) {
 			(this as any).api('i/update', {
-				auto_watch: v
+				autoWatch: v
 			});
 		},
 		onChangeShowPostFormOnTopOfTl(v) {
diff --git a/src/web/app/desktop/views/components/timeline.vue b/src/web/app/desktop/views/components/timeline.vue
index c0eae2cd9e..65b4bd1c7a 100644
--- a/src/web/app/desktop/views/components/timeline.vue
+++ b/src/web/app/desktop/views/components/timeline.vue
@@ -65,7 +65,7 @@ export default Vue.extend({
 
 			(this as any).api('posts/timeline', {
 				limit: 11,
-				until_date: this.date ? this.date.getTime() : undefined
+				untilDate: this.date ? this.date.getTime() : undefined
 			}).then(posts => {
 				if (posts.length == 11) {
 					posts.pop();
@@ -82,7 +82,7 @@ export default Vue.extend({
 			this.moreFetching = true;
 			(this as any).api('posts/timeline', {
 				limit: 11,
-				until_id: this.posts[this.posts.length - 1].id
+				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
 				if (posts.length == 11) {
 					posts.pop();
diff --git a/src/web/app/desktop/views/components/ui.header.account.vue b/src/web/app/desktop/views/components/ui.header.account.vue
index 19b9d77798..ec4635f338 100644
--- a/src/web/app/desktop/views/components/ui.header.account.vue
+++ b/src/web/app/desktop/views/components/ui.header.account.vue
@@ -2,7 +2,7 @@
 <div class="account">
 	<button class="header" :data-active="isOpen" @click="toggle">
 		<span class="username">{{ os.i.username }}<template v-if="!isOpen">%fa:angle-down%</template><template v-if="isOpen">%fa:angle-up%</template></span>
-		<img class="avatar" :src="`${ os.i.avatar_url }?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${ os.i.avatarUrl }?thumbnail&size=64`" alt="avatar"/>
 	</button>
 	<transition name="zoom-in-top">
 		<div class="menu" v-if="isOpen">
diff --git a/src/web/app/desktop/views/components/user-preview.vue b/src/web/app/desktop/views/components/user-preview.vue
index 4535ad8902..8c86b2efe8 100644
--- a/src/web/app/desktop/views/components/user-preview.vue
+++ b/src/web/app/desktop/views/components/user-preview.vue
@@ -1,9 +1,9 @@
 <template>
 <div class="mk-user-preview">
 	<template v-if="u != null">
-		<div class="banner" :style="u.banner_url ? `background-image: url(${u.banner_url}?thumbnail&size=512)` : ''"></div>
+		<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl}?thumbnail&size=512)` : ''"></div>
 		<router-link class="avatar" :to="`/@${acct}`">
-			<img :src="`${u.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img :src="`${u.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 		<div class="title">
 			<router-link class="name" :to="`/@${acct}`">{{ u.name }}</router-link>
diff --git a/src/web/app/desktop/views/components/users-list.item.vue b/src/web/app/desktop/views/components/users-list.item.vue
index e02d1311d2..c2f30cf382 100644
--- a/src/web/app/desktop/views/components/users-list.item.vue
+++ b/src/web/app/desktop/views/components/users-list.item.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="root item">
 	<router-link class="avatar-anchor" :to="`/@${acct}`" v-user-preview="user.id">
-		<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/desktop/views/pages/user/user.followers-you-know.vue b/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
index 9f67f5cf76..d0dab6c3df 100644
--- a/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
+++ b/src/web/app/desktop/views/pages/user/user.followers-you-know.vue
@@ -4,7 +4,7 @@
 	<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.followers-you-know.loading%<mk-ellipsis/></p>
 	<div v-if="!fetching && users.length > 0">
 	<router-link v-for="user in users" :to="`/@${getAcct(user)}`" :key="user.id">
-		<img :src="`${user.avatar_url}?thumbnail&size=64`" :alt="user.name" v-user-preview="user.id"/>
+		<img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user.name" v-user-preview="user.id"/>
 	</router-link>
 	</div>
 	<p class="empty" v-if="!fetching && users.length == 0">%i18n:desktop.tags.mk-user.followers-you-know.no-users%</p>
diff --git a/src/web/app/desktop/views/pages/user/user.friends.vue b/src/web/app/desktop/views/pages/user/user.friends.vue
index cc0bcef257..3ec30fb438 100644
--- a/src/web/app/desktop/views/pages/user/user.friends.vue
+++ b/src/web/app/desktop/views/pages/user/user.friends.vue
@@ -5,7 +5,7 @@
 	<template v-if="!fetching && users.length != 0">
 		<div class="user" v-for="friend in users">
 			<router-link class="avatar-anchor" :to="`/@${getAcct(friend)}`">
-				<img class="avatar" :src="`${friend.avatar_url}?thumbnail&size=42`" alt="" v-user-preview="friend.id"/>
+				<img class="avatar" :src="`${friend.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="friend.id"/>
 			</router-link>
 			<div class="body">
 				<router-link class="name" :to="`/@${getAcct(friend)}`" v-user-preview="friend.id">{{ friend.name }}</router-link>
diff --git a/src/web/app/desktop/views/pages/user/user.header.vue b/src/web/app/desktop/views/pages/user/user.header.vue
index 3522e76bdb..54f431fd2e 100644
--- a/src/web/app/desktop/views/pages/user/user.header.vue
+++ b/src/web/app/desktop/views/pages/user/user.header.vue
@@ -1,11 +1,11 @@
 <template>
-<div class="header" :data-is-dark-background="user.banner_url != null">
-	<div class="banner-container" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=2048)` : ''">
-		<div class="banner" ref="banner" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=2048)` : ''" @click="onBannerClick"></div>
+<div class="header" :data-is-dark-background="user.bannerUrl != null">
+	<div class="banner-container" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=2048)` : ''">
+		<div class="banner" ref="banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=2048)` : ''" @click="onBannerClick"></div>
 	</div>
 	<div class="fade"></div>
 	<div class="container">
-		<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=150`" alt="avatar"/>
+		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=150`" alt="avatar"/>
 		<div class="title">
 			<p class="name">{{ user.name }}</p>
 			<p class="username">@{{ acct }}</p>
@@ -59,7 +59,7 @@ export default Vue.extend({
 			if (!(this as any).os.isSignedIn || (this as any).os.i.id != this.user.id) return;
 
 			(this as any).apis.updateBanner((this as any).os.i, i => {
-				this.user.banner_url = i.banner_url;
+				this.user.bannerUrl = i.bannerUrl;
 			});
 		}
 	}
diff --git a/src/web/app/desktop/views/pages/user/user.timeline.vue b/src/web/app/desktop/views/pages/user/user.timeline.vue
index 1f0d0b1985..134ad423ce 100644
--- a/src/web/app/desktop/views/pages/user/user.timeline.vue
+++ b/src/web/app/desktop/views/pages/user/user.timeline.vue
@@ -62,7 +62,7 @@ export default Vue.extend({
 		fetch(cb?) {
 			(this as any).api('users/posts', {
 				userId: this.user.id,
-				until_date: this.date ? this.date.getTime() : undefined,
+				untilDate: this.date ? this.date.getTime() : undefined,
 				with_replies: this.mode == 'with-replies'
 			}).then(posts => {
 				this.posts = posts;
@@ -76,7 +76,7 @@ export default Vue.extend({
 			(this as any).api('users/posts', {
 				userId: this.user.id,
 				with_replies: this.mode == 'with-replies',
-				until_id: this.posts[this.posts.length - 1].id
+				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
 				this.moreFetching = false;
 				this.posts = this.posts.concat(posts);
diff --git a/src/web/app/desktop/views/pages/welcome.vue b/src/web/app/desktop/views/pages/welcome.vue
index 927ddf575b..34c28854b1 100644
--- a/src/web/app/desktop/views/pages/welcome.vue
+++ b/src/web/app/desktop/views/pages/welcome.vue
@@ -9,7 +9,7 @@
 					<p><button class="signup" @click="signup">はじめる</button><button class="signin" @click="signin">ログイン</button></p>
 					<div class="users">
 						<router-link v-for="user in users" :key="user.id" class="avatar-anchor" :to="`/@${getAcct(user)}`" v-user-preview="user.id">
-							<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+							<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 						</router-link>
 					</div>
 				</div>
diff --git a/src/web/app/desktop/views/widgets/profile.vue b/src/web/app/desktop/views/widgets/profile.vue
index 3940106197..83cd67b50c 100644
--- a/src/web/app/desktop/views/widgets/profile.vue
+++ b/src/web/app/desktop/views/widgets/profile.vue
@@ -4,12 +4,12 @@
 	:data-melt="props.design == 2"
 >
 	<div class="banner"
-		:style="os.i.banner_url ? `background-image: url(${os.i.banner_url}?thumbnail&size=256)` : ''"
+		:style="os.i.bannerUrl ? `background-image: url(${os.i.bannerUrl}?thumbnail&size=256)` : ''"
 		title="クリックでバナー編集"
 		@click="os.apis.updateBanner"
 	></div>
 	<img class="avatar"
-		:src="`${os.i.avatar_url}?thumbnail&size=96`"
+		:src="`${os.i.avatarUrl}?thumbnail&size=96`"
 		@click="os.apis.updateAvatar"
 		alt="avatar"
 		title="クリックでアバター編集"
diff --git a/src/web/app/desktop/views/widgets/users.vue b/src/web/app/desktop/views/widgets/users.vue
index 10e3c529ee..7b89441126 100644
--- a/src/web/app/desktop/views/widgets/users.vue
+++ b/src/web/app/desktop/views/widgets/users.vue
@@ -8,7 +8,7 @@
 	<template v-else-if="users.length != 0">
 		<div class="user" v-for="_user in users">
 			<router-link class="avatar-anchor" :to="`/@${getAcct(_user)}`">
-				<img class="avatar" :src="`${_user.avatar_url}?thumbnail&size=42`" alt="" v-user-preview="_user.id"/>
+				<img class="avatar" :src="`${_user.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="_user.id"/>
 			</router-link>
 			<div class="body">
 				<router-link class="name" :to="`/@${getAcct(_user)}`" v-user-preview="_user.id">{{ _user.name }}</router-link>
diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue
index cd07cc4d49..e407ca00d7 100644
--- a/src/web/app/dev/views/new-app.vue
+++ b/src/web/app/dev/views/new-app.vue
@@ -92,7 +92,7 @@ export default Vue.extend({
 				name: this.name,
 				nameId: this.nid,
 				description: this.description,
-				callback_url: this.cb,
+				callbackUrl: this.cb,
 				permission: this.permission
 			}).then(() => {
 				location.href = '/apps';
diff --git a/src/web/app/mobile/views/components/drive.vue b/src/web/app/mobile/views/components/drive.vue
index dd4d97e960..5affbdaf1f 100644
--- a/src/web/app/mobile/views/components/drive.vue
+++ b/src/web/app/mobile/views/components/drive.vue
@@ -320,7 +320,7 @@ export default Vue.extend({
 			(this as any).api('drive/files', {
 				folderId: this.folder ? this.folder.id : null,
 				limit: max + 1,
-				until_id: this.files[this.files.length - 1].id
+				untilId: this.files[this.files.length - 1].id
 			}).then(files => {
 				if (files.length == max + 1) {
 					this.moreFiles = true;
diff --git a/src/web/app/mobile/views/components/notification-preview.vue b/src/web/app/mobile/views/components/notification-preview.vue
index 47df626fa8..fce9ed82f9 100644
--- a/src/web/app/mobile/views/components/notification-preview.vue
+++ b/src/web/app/mobile/views/components/notification-preview.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-notification-preview" :class="notification.type">
 	<template v-if="notification.type == 'reaction'">
-		<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p><mk-reaction-icon :reaction="notification.reaction"/>{{ notification.user.name }}</p>
 			<p class="post-ref">%fa:quote-left%{{ getPostSummary(notification.post) }}%fa:quote-right%</p>
@@ -9,7 +9,7 @@
 	</template>
 
 	<template v-if="notification.type == 'repost'">
-		<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:retweet%{{ notification.post.user.name }}</p>
 			<p class="post-ref">%fa:quote-left%{{ getPostSummary(notification.post.repost) }}%fa:quote-right%</p>
@@ -17,7 +17,7 @@
 	</template>
 
 	<template v-if="notification.type == 'quote'">
-		<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:quote-left%{{ notification.post.user.name }}</p>
 			<p class="post-preview">{{ getPostSummary(notification.post) }}</p>
@@ -25,14 +25,14 @@
 	</template>
 
 	<template v-if="notification.type == 'follow'">
-		<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:user-plus%{{ notification.user.name }}</p>
 		</div>
 	</template>
 
 	<template v-if="notification.type == 'reply'">
-		<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:reply%{{ notification.post.user.name }}</p>
 			<p class="post-preview">{{ getPostSummary(notification.post) }}</p>
@@ -40,7 +40,7 @@
 	</template>
 
 	<template v-if="notification.type == 'mention'">
-		<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:at%{{ notification.post.user.name }}</p>
 			<p class="post-preview">{{ getPostSummary(notification.post) }}</p>
@@ -48,7 +48,7 @@
 	</template>
 
 	<template v-if="notification.type == 'poll_vote'">
-		<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		<div class="text">
 			<p>%fa:chart-pie%{{ notification.user.name }}</p>
 			<p class="post-ref">%fa:quote-left%{{ getPostSummary(notification.post) }}%fa:quote-right%</p>
diff --git a/src/web/app/mobile/views/components/notification.vue b/src/web/app/mobile/views/components/notification.vue
index aac8f82900..e221fb3ac4 100644
--- a/src/web/app/mobile/views/components/notification.vue
+++ b/src/web/app/mobile/views/components/notification.vue
@@ -3,7 +3,7 @@
 	<div class="notification reaction" v-if="notification.type == 'reaction'">
 		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 		<div class="text">
 			<p>
@@ -20,7 +20,7 @@
 	<div class="notification repost" v-if="notification.type == 'repost'">
 		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${notification.post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img class="avatar" :src="`${notification.post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 		<div class="text">
 			<p>
@@ -40,7 +40,7 @@
 	<div class="notification follow" v-if="notification.type == 'follow'">
 		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 		<div class="text">
 			<p>
@@ -61,7 +61,7 @@
 	<div class="notification poll_vote" v-if="notification.type == 'poll_vote'">
 		<mk-time :time="notification.createdAt"/>
 		<router-link class="avatar-anchor" :to="`/@${acct}`">
-			<img class="avatar" :src="`${notification.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 		<div class="text">
 			<p>
diff --git a/src/web/app/mobile/views/components/notifications.vue b/src/web/app/mobile/views/components/notifications.vue
index 4365198f16..d68b990dfa 100644
--- a/src/web/app/mobile/views/components/notifications.vue
+++ b/src/web/app/mobile/views/components/notifications.vue
@@ -75,7 +75,7 @@ export default Vue.extend({
 
 			(this as any).api('i/notifications', {
 				limit: max + 1,
-				until_id: this.notifications[this.notifications.length - 1].id
+				untilId: this.notifications[this.notifications.length - 1].id
 			}).then(notifications => {
 				if (notifications.length == max + 1) {
 					this.moreNotifications = true;
diff --git a/src/web/app/mobile/views/components/post-detail.sub.vue b/src/web/app/mobile/views/components/post-detail.sub.vue
index 427e054fd6..db7567834a 100644
--- a/src/web/app/mobile/views/components/post-detail.sub.vue
+++ b/src/web/app/mobile/views/components/post-detail.sub.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="root sub">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index 9a8c33a80d..241782aa5f 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -18,7 +18,7 @@
 	<div class="repost" v-if="isRepost">
 		<p>
 			<router-link class="avatar-anchor" :to="`/@${acct}`">
-				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=32`" alt="avatar"/>
+				<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
 			<router-link class="name" :to="`/@${acct}`">
@@ -30,7 +30,7 @@
 	<article>
 		<header>
 			<router-link class="avatar-anchor" :to="`/@${pAcct}`">
-				<img class="avatar" :src="`${p.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+				<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 			</router-link>
 			<div>
 				<router-link class="name" :to="`/@${pAcct}`">{{ p.user.name }}</router-link>
diff --git a/src/web/app/mobile/views/components/post-preview.vue b/src/web/app/mobile/views/components/post-preview.vue
index e640843419..a6141dc8e3 100644
--- a/src/web/app/mobile/views/components/post-preview.vue
+++ b/src/web/app/mobile/views/components/post-preview.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-post-preview">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/mobile/views/components/post.sub.vue b/src/web/app/mobile/views/components/post.sub.vue
index 8a11239da7..adf444a2d6 100644
--- a/src/web/app/mobile/views/components/post.sub.vue
+++ b/src/web/app/mobile/views/components/post.sub.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="sub">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=96`" alt="avatar"/>
+		<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue
index 243e7d9c2e..0c6522db86 100644
--- a/src/web/app/mobile/views/components/post.vue
+++ b/src/web/app/mobile/views/components/post.vue
@@ -6,7 +6,7 @@
 	<div class="repost" v-if="isRepost">
 		<p>
 			<router-link class="avatar-anchor" :to="`/@${acct}`">
-				<img class="avatar" :src="`${post.user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+				<img class="avatar" :src="`${post.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 			</router-link>
 			%fa:retweet%
 			<span>{{ '%i18n:mobile.tags.mk-timeline-post.reposted-by%'.substr(0, '%i18n:mobile.tags.mk-timeline-post.reposted-by%'.indexOf('{')) }}</span>
@@ -17,7 +17,7 @@
 	</div>
 	<article>
 		<router-link class="avatar-anchor" :to="`/@${pAcct}`">
-			<img class="avatar" :src="`${p.user.avatar_url}?thumbnail&size=96`" alt="avatar"/>
+			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 		</router-link>
 		<div class="main">
 			<header>
diff --git a/src/web/app/mobile/views/components/timeline.vue b/src/web/app/mobile/views/components/timeline.vue
index 999f4a1f1e..7b5948faf1 100644
--- a/src/web/app/mobile/views/components/timeline.vue
+++ b/src/web/app/mobile/views/components/timeline.vue
@@ -65,7 +65,7 @@ export default Vue.extend({
 			this.fetching = true;
 			(this as any).api('posts/timeline', {
 				limit: limit + 1,
-				until_date: this.date ? (this.date as any).getTime() : undefined
+				untilDate: this.date ? (this.date as any).getTime() : undefined
 			}).then(posts => {
 				if (posts.length == limit + 1) {
 					posts.pop();
@@ -81,7 +81,7 @@ export default Vue.extend({
 			this.moreFetching = true;
 			(this as any).api('posts/timeline', {
 				limit: limit + 1,
-				until_id: this.posts[this.posts.length - 1].id
+				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
 				if (posts.length == limit + 1) {
 					posts.pop();
diff --git a/src/web/app/mobile/views/components/ui.nav.vue b/src/web/app/mobile/views/components/ui.nav.vue
index 760a5b5184..a923774a73 100644
--- a/src/web/app/mobile/views/components/ui.nav.vue
+++ b/src/web/app/mobile/views/components/ui.nav.vue
@@ -10,7 +10,7 @@
 	<transition name="nav">
 		<div class="body" v-if="isOpen">
 			<router-link class="me" v-if="os.isSignedIn" :to="`/@${os.i.username}`">
-				<img class="avatar" :src="`${os.i.avatar_url}?thumbnail&size=128`" alt="avatar"/>
+				<img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=128`" alt="avatar"/>
 				<p class="name">{{ os.i.name }}</p>
 			</router-link>
 			<div class="links">
diff --git a/src/web/app/mobile/views/components/user-card.vue b/src/web/app/mobile/views/components/user-card.vue
index 5a7309cfd3..ffa1100519 100644
--- a/src/web/app/mobile/views/components/user-card.vue
+++ b/src/web/app/mobile/views/components/user-card.vue
@@ -1,8 +1,8 @@
 <template>
 <div class="mk-user-card">
-	<header :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=1024)` : ''">
+	<header :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=1024)` : ''">
 		<a :href="`/@${acct}`">
-			<img :src="`${user.avatar_url}?thumbnail&size=200`" alt="avatar"/>
+			<img :src="`${user.avatarUrl}?thumbnail&size=200`" alt="avatar"/>
 		</a>
 	</header>
 	<a class="name" :href="`/@${acct}`" target="_blank">{{ user.name }}</a>
diff --git a/src/web/app/mobile/views/components/user-preview.vue b/src/web/app/mobile/views/components/user-preview.vue
index be80582cac..e51e4353d3 100644
--- a/src/web/app/mobile/views/components/user-preview.vue
+++ b/src/web/app/mobile/views/components/user-preview.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-user-preview">
 	<router-link class="avatar-anchor" :to="`/@${acct}`">
-		<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 	</router-link>
 	<div class="main">
 		<header>
diff --git a/src/web/app/mobile/views/components/user-timeline.vue b/src/web/app/mobile/views/components/user-timeline.vue
index 73ff440dc2..d1f771f812 100644
--- a/src/web/app/mobile/views/components/user-timeline.vue
+++ b/src/web/app/mobile/views/components/user-timeline.vue
@@ -53,7 +53,7 @@ export default Vue.extend({
 				userId: this.user.id,
 				with_media: this.withMedia,
 				limit: limit + 1,
-				until_id: this.posts[this.posts.length - 1].id
+				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
 				if (posts.length == limit + 1) {
 					posts.pop();
diff --git a/src/web/app/mobile/views/pages/followers.vue b/src/web/app/mobile/views/pages/followers.vue
index b5267bebf4..08a15f945a 100644
--- a/src/web/app/mobile/views/pages/followers.vue
+++ b/src/web/app/mobile/views/pages/followers.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<template slot="header" v-if="!fetching">
-		<img :src="`${user.avatar_url}?thumbnail&size=64`" alt="">
+		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
 		{{ '%i18n:mobile.tags.mk-user-followers-page.followers-of%'.replace('{}', user.name) }}
 	</template>
 	<mk-users-list
diff --git a/src/web/app/mobile/views/pages/following.vue b/src/web/app/mobile/views/pages/following.vue
index d8c31c9f01..ecdaa5a586 100644
--- a/src/web/app/mobile/views/pages/following.vue
+++ b/src/web/app/mobile/views/pages/following.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<template slot="header" v-if="!fetching">
-		<img :src="`${user.avatar_url}?thumbnail&size=64`" alt="">
+		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
 		{{ '%i18n:mobile.tags.mk-user-following-page.following-of%'.replace('{}', user.name) }}
 	</template>
 	<mk-users-list
diff --git a/src/web/app/mobile/views/pages/notifications.vue b/src/web/app/mobile/views/pages/notifications.vue
index 3dcfb2f38c..6d45e22a9c 100644
--- a/src/web/app/mobile/views/pages/notifications.vue
+++ b/src/web/app/mobile/views/pages/notifications.vue
@@ -22,7 +22,7 @@ export default Vue.extend({
 			const ok = window.confirm('%i18n:mobile.tags.mk-notifications-page.read-all%');
 			if (!ok) return;
 
-			(this as any).api('notifications/mark_as_read_all');
+			(this as any).api('notifications/markAsRead_all');
 		},
 		onFetched() {
 			Progress.done();
diff --git a/src/web/app/mobile/views/pages/profile-setting.vue b/src/web/app/mobile/views/pages/profile-setting.vue
index d4bb254877..15f9bc9b68 100644
--- a/src/web/app/mobile/views/pages/profile-setting.vue
+++ b/src/web/app/mobile/views/pages/profile-setting.vue
@@ -4,8 +4,8 @@
 	<div :class="$style.content">
 		<p>%fa:info-circle%%i18n:mobile.tags.mk-profile-setting.will-be-published%</p>
 		<div :class="$style.form">
-			<div :style="os.i.banner_url ? `background-image: url(${os.i.banner_url}?thumbnail&size=1024)` : ''" @click="setBanner">
-				<img :src="`${os.i.avatar_url}?thumbnail&size=200`" alt="avatar" @click="setAvatar"/>
+			<div :style="os.i.bannerUrl ? `background-image: url(${os.i.bannerUrl}?thumbnail&size=1024)` : ''" @click="setBanner">
+				<img :src="`${os.i.avatarUrl}?thumbnail&size=200`" alt="avatar" @click="setAvatar"/>
 			</div>
 			<label>
 				<p>%i18n:mobile.tags.mk-profile-setting.name%</p>
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index c4d6b67e6c..f5bbd41625 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -3,11 +3,11 @@
 	<span slot="header" v-if="!fetching">%fa:user% {{ user.name }}</span>
 	<main v-if="!fetching">
 		<header>
-			<div class="banner" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=1024)` : ''"></div>
+			<div class="banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=1024)` : ''"></div>
 			<div class="body">
 				<div class="top">
 					<a class="avatar">
-						<img :src="`${user.avatar_url}?thumbnail&size=200`" alt="avatar"/>
+						<img :src="`${user.avatarUrl}?thumbnail&size=200`" alt="avatar"/>
 					</a>
 					<mk-follow-button v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
 				</div>
diff --git a/src/web/app/mobile/views/pages/user/home.followers-you-know.vue b/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
index 508ab4b4a7..8c84d2dbba 100644
--- a/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
+++ b/src/web/app/mobile/views/pages/user/home.followers-you-know.vue
@@ -3,7 +3,7 @@
 	<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:mobile.tags.mk-user-overview-followers-you-know.loading%<mk-ellipsis/></p>
 	<div v-if="!fetching && users.length > 0">
 		<a v-for="user in users" :key="user.id" :href="`/@${getAcct(user)}`">
-			<img :src="`${user.avatar_url}?thumbnail&size=64`" :alt="user.name"/>
+			<img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user.name"/>
 		</a>
 	</div>
 	<p class="empty" v-if="!fetching && users.length == 0">%i18n:mobile.tags.mk-user-overview-followers-you-know.no-users%</p>
diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue
index 7a809702c5..17cdf93065 100644
--- a/src/web/app/mobile/views/pages/welcome.vue
+++ b/src/web/app/mobile/views/pages/welcome.vue
@@ -22,7 +22,7 @@
 	</div>
 	<div class="users">
 		<router-link v-for="user in users" :key="user.id" class="avatar-anchor" :to="`/@${user.username}`">
-			<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=64`" alt="avatar"/>
+			<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 		</router-link>
 	</div>
 	<footer>
diff --git a/src/web/app/mobile/views/widgets/profile.vue b/src/web/app/mobile/views/widgets/profile.vue
index 1c9d038b4c..f1d283e45a 100644
--- a/src/web/app/mobile/views/widgets/profile.vue
+++ b/src/web/app/mobile/views/widgets/profile.vue
@@ -2,10 +2,10 @@
 <div class="mkw-profile">
 	<mk-widget-container>
 		<div :class="$style.banner"
-			:style="os.i.banner_url ? `background-image: url(${os.i.banner_url}?thumbnail&size=256)` : ''"
+			:style="os.i.bannerUrl ? `background-image: url(${os.i.bannerUrl}?thumbnail&size=256)` : ''"
 		></div>
 		<img :class="$style.avatar"
-			:src="`${os.i.avatar_url}?thumbnail&size=96`"
+			:src="`${os.i.avatarUrl}?thumbnail&size=96`"
 			alt="avatar"
 		/>
 		<router-link :class="$style.name" :to="`/@${os.i.username}`">{{ os.i.name }}</router-link>
diff --git a/src/web/docs/api.ja.pug b/src/web/docs/api.ja.pug
index 2bb08f7f32..665cfdc4b8 100644
--- a/src/web/docs/api.ja.pug
+++ b/src/web/docs/api.ja.pug
@@ -54,7 +54,7 @@ section
 		h3 2.ユーザーに認証させる
 		p あなたのアプリを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。
 		p
-			| 認証セッションを開始するには、#{common.config.api_url}/auth/session/generate へパラメータに app_secret としてシークレットキーを含めたリクエストを送信します。
+			| 認証セッションを開始するには、#{common.config.api_url}/auth/session/generate へパラメータに appSecret としてシークレットキーを含めたリクエストを送信します。
 			| リクエスト形式はJSONで、メソッドはPOSTです。
 			| レスポンスとして認証セッションのトークンや認証フォームのURLが取得できるので、認証フォームのURLをブラウザで表示し、ユーザーにフォームを提示してください。
 
@@ -76,7 +76,7 @@ section
 					th 説明
 			tbody
 				tr
-					td app_secret
+					td appSecret
 					td string
 					td あなたのアプリのシークレットキー
 				tr
diff --git a/src/web/docs/api/endpoints/posts/timeline.yaml b/src/web/docs/api/endpoints/posts/timeline.yaml
index 01976b0611..9c44dd736a 100644
--- a/src/web/docs/api/endpoints/posts/timeline.yaml
+++ b/src/web/docs/api/endpoints/posts/timeline.yaml
@@ -10,22 +10,22 @@ params:
     optional: true
     desc:
       ja: "取得する最大の数"
-  - name: "since_id"
+  - name: "sinceId"
     type: "id(Post)"
     optional: true
     desc:
       ja: "指定すると、この投稿を基点としてより新しい投稿を取得します"
-  - name: "until_id"
+  - name: "untilId"
     type: "id(Post)"
     optional: true
     desc:
       ja: "指定すると、この投稿を基点としてより古い投稿を取得します"
-  - name: "since_date"
+  - name: "sinceDate"
     type: "number"
     optional: true
     desc:
       ja: "指定した時間を基点としてより新しい投稿を取得します。数値は、1970 年 1 月 1 日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。"
-  - name: "until_date"
+  - name: "untilDate"
     type: "number"
     optional: true
     desc:
diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml
index 60f2c86084..f45455e731 100644
--- a/src/web/docs/api/entities/user.yaml
+++ b/src/web/docs/api/entities/user.yaml
@@ -35,7 +35,7 @@ props:
     desc:
       ja: "アバターのID"
       en: "The ID of the avatar of this user"
-  - name: "avatar_url"
+  - name: "avatarUrl"
     type: "string"
     optional: false
     desc:
@@ -47,7 +47,7 @@ props:
     desc:
       ja: "バナーのID"
       en: "The ID of the banner of this user"
-  - name: "banner_url"
+  - name: "bannerUrl"
     type: "string"
     optional: false
     desc:
diff --git a/swagger.js b/swagger.js
index f6c2ca7fde..ebd7a356e9 100644
--- a/swagger.js
+++ b/swagger.js
@@ -83,7 +83,7 @@ const defaultSwagger = {
           "type": "string",
           "description": "アバターに設定しているドライブのファイルのID"
         },
-        "avatar_url": {
+        "avatarUrl": {
           "type": "string",
           "description": "アバターURL"
         },
@@ -91,7 +91,7 @@ const defaultSwagger = {
           "type": "string",
           "description": "バナーに設定しているドライブのファイルのID"
         },
-        "banner_url": {
+        "bannerUrl": {
           "type": "string",
           "description": "バナーURL"
         },

From 71065077f66662381a6d5f08ad8b345ceaf742db Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 16:59:11 +0900
Subject: [PATCH 22/43] wip

---
 src/api/endpoints/meta.ts                      |  1 -
 src/api/endpoints/othello/games/show.ts        |  6 +++---
 src/api/endpoints/posts/create.ts              | 16 ++++++++--------
 src/api/endpoints/posts/reactions/create.ts    |  2 +-
 src/api/endpoints/posts/reactions/delete.ts    |  2 +-
 src/api/endpoints/posts/search.ts              | 18 +++++++++---------
 src/api/endpoints/posts/trend.ts               |  4 ++--
 src/api/endpoints/stats.ts                     |  4 ++--
 src/api/endpoints/users/posts.ts               | 12 ++++++------
 src/api/models/app.ts                          |  2 +-
 src/api/models/channel.ts                      |  2 +-
 src/api/models/drive-folder.ts                 |  4 ++--
 src/api/models/post.ts                         |  6 +++++-
 src/api/models/user.ts                         | 14 +++++++-------
 src/web/app/auth/views/index.vue               |  4 ++--
 src/web/app/ch/tags/channel.tag                |  8 ++++----
 .../app/common/scripts/parse-search-query.ts   |  4 ++--
 .../components/messaging-room.message.vue      |  4 ++--
 .../app/common/views/components/othello.vue    |  2 +-
 src/web/app/common/views/components/poll.vue   |  8 ++++----
 .../views/components/reactions-viewer.vue      |  2 +-
 .../desktop/views/components/follow-button.vue | 18 +++++++++---------
 .../app/desktop/views/components/followers.vue |  2 +-
 .../app/desktop/views/components/following.vue |  2 +-
 .../desktop/views/components/post-detail.vue   | 10 +++++-----
 .../desktop/views/components/posts.post.vue    | 10 +++++-----
 .../views/components/users-list.item.vue       |  2 +-
 src/web/app/desktop/views/pages/othello.vue    |  2 +-
 .../desktop/views/pages/user/user.photos.vue   |  2 +-
 .../desktop/views/pages/user/user.profile.vue  | 10 +++++-----
 src/web/app/mobile/views/components/drive.vue  |  8 ++++----
 .../mobile/views/components/follow-button.vue  | 18 +++++++++---------
 .../mobile/views/components/post-detail.vue    | 10 +++++-----
 src/web/app/mobile/views/components/post.vue   | 10 +++++-----
 .../mobile/views/components/user-timeline.vue  |  4 ++--
 src/web/app/mobile/views/pages/followers.vue   |  2 +-
 src/web/app/mobile/views/pages/following.vue   |  2 +-
 src/web/app/mobile/views/pages/othello.vue     |  2 +-
 src/web/app/mobile/views/pages/user.vue        |  2 +-
 .../mobile/views/pages/user/home.photos.vue    |  2 +-
 src/web/app/stats/tags/index.tag               |  2 +-
 src/web/docs/api/entities/post.yaml            |  4 ++--
 src/web/docs/api/entities/user.yaml            |  6 +++---
 tools/migration/shell.camel-case.js            |  3 +++
 44 files changed, 132 insertions(+), 126 deletions(-)

diff --git a/src/api/endpoints/meta.ts b/src/api/endpoints/meta.ts
index 1370ead3c5..80a3725eb0 100644
--- a/src/api/endpoints/meta.ts
+++ b/src/api/endpoints/meta.ts
@@ -53,7 +53,6 @@ module.exports = (params) => new Promise(async (res, rej) => {
 			model: os.cpus()[0].model,
 			cores: os.cpus().length
 		},
-		top_image: meta.top_image,
 		broadcasts: meta.broadcasts
 	});
 });
diff --git a/src/api/endpoints/othello/games/show.ts b/src/api/endpoints/othello/games/show.ts
index 19f5d0fef0..f9084682fa 100644
--- a/src/api/endpoints/othello/games/show.ts
+++ b/src/api/endpoints/othello/games/show.ts
@@ -3,9 +3,9 @@ import OthelloGame, { pack } from '../../../models/othello-game';
 import Othello from '../../../../common/othello/core';
 
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	// Get 'game_id' parameter
-	const [gameId, gameIdErr] = $(params.game_id).id().$;
-	if (gameIdErr) return rej('invalid game_id param');
+	// Get 'gameId' parameter
+	const [gameId, gameIdErr] = $(params.gameId).id().$;
+	if (gameIdErr) return rej('invalid gameId param');
 
 	const game = await OthelloGame.findOne({ _id: gameId });
 
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index b99d1fbbc1..2817374545 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -211,12 +211,12 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 	// 直近の投稿と重複してたらエラー
 	// TODO: 直近の投稿が一日前くらいなら重複とは見なさない
-	if (user.latest_post) {
+	if (user.latestPost) {
 		if (deepEqual({
-			text: user.latest_post.text,
-			reply: user.latest_post.replyId ? user.latest_post.replyId.toString() : null,
-			repost: user.latest_post.repostId ? user.latest_post.repostId.toString() : null,
-			mediaIds: (user.latest_post.mediaIds || []).map(id => id.toString())
+			text: user.latestPost.text,
+			reply: user.latestPost.replyId ? user.latestPost.replyId.toString() : null,
+			repost: user.latestPost.repostId ? user.latestPost.repostId.toString() : null,
+			mediaIds: (user.latestPost.mediaIds || []).map(id => id.toString())
 		}, {
 			text: text,
 			reply: reply ? reply._id.toString() : null,
@@ -277,7 +277,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 	User.update({ _id: user._id }, {
 		$set: {
-			latest_post: post
+			latestPost: post
 		}
 	});
 
@@ -362,7 +362,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 		// Increment replies count
 		Post.update({ _id: reply._id }, {
 			$inc: {
-				replies_count: 1
+				repliesCount: 1
 			}
 		});
 
@@ -457,7 +457,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 			// Update repostee status
 			Post.update({ _id: repost._id }, {
 				$inc: {
-					repost_count: 1
+					repostCount: 1
 				}
 			});
 		}
diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts
index 6f75a923cd..a1e6779805 100644
--- a/src/api/endpoints/posts/reactions/create.ts
+++ b/src/api/endpoints/posts/reactions/create.ts
@@ -73,7 +73,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	res();
 
 	const inc = {};
-	inc[`reaction_counts.${reaction}`] = 1;
+	inc[`reactionCounts.${reaction}`] = 1;
 
 	// Increment reactions count
 	await Post.update({ _id: post._id }, {
diff --git a/src/api/endpoints/posts/reactions/delete.ts b/src/api/endpoints/posts/reactions/delete.ts
index 18fdabcdc2..b09bcbb4b7 100644
--- a/src/api/endpoints/posts/reactions/delete.ts
+++ b/src/api/endpoints/posts/reactions/delete.ts
@@ -51,7 +51,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	res();
 
 	const dec = {};
-	dec[`reaction_counts.${exist.reaction}`] = -1;
+	dec[`reactionCounts.${exist.reaction}`] = -1;
 
 	// Decrement reactions count
 	Post.update({ _id: post._id }, {
diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts
index f90b9aa0dd..5c324bfe9a 100644
--- a/src/api/endpoints/posts/search.ts
+++ b/src/api/endpoints/posts/search.ts
@@ -21,21 +21,21 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [text, textError] = $(params.text).optional.string().$;
 	if (textError) return rej('invalid text param');
 
-	// Get 'include_userIds' parameter
-	const [includeUserIds = [], includeUserIdsErr] = $(params.include_userIds).optional.array('id').$;
-	if (includeUserIdsErr) return rej('invalid include_userIds param');
+	// Get 'includeUserIds' parameter
+	const [includeUserIds = [], includeUserIdsErr] = $(params.includeUserIds).optional.array('id').$;
+	if (includeUserIdsErr) return rej('invalid includeUserIds param');
 
 	// Get 'exclude_userIds' parameter
 	const [excludeUserIds = [], excludeUserIdsErr] = $(params.exclude_userIds).optional.array('id').$;
 	if (excludeUserIdsErr) return rej('invalid exclude_userIds param');
 
-	// Get 'include_user_usernames' parameter
-	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.include_user_usernames).optional.array('string').$;
-	if (includeUserUsernamesErr) return rej('invalid include_user_usernames param');
+	// Get 'includeUserUsernames' parameter
+	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.includeUserUsernames).optional.array('string').$;
+	if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param');
 
-	// Get 'exclude_user_usernames' parameter
-	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.exclude_user_usernames).optional.array('string').$;
-	if (excludeUserUsernamesErr) return rej('invalid exclude_user_usernames param');
+	// Get 'exclude_userUsernames' parameter
+	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.exclude_userUsernames).optional.array('string').$;
+	if (excludeUserUsernamesErr) return rej('invalid exclude_userUsernames param');
 
 	// Get 'following' parameter
 	const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$;
diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts
index 3f92f06167..bc0c47fbc6 100644
--- a/src/api/endpoints/posts/trend.ts
+++ b/src/api/endpoints/posts/trend.ts
@@ -41,7 +41,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		createdAt: {
 			$gte: new Date(Date.now() - ms('1days'))
 		},
-		repost_count: {
+		repostCount: {
 			$gt: 0
 		}
 	} as any;
@@ -68,7 +68,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 			limit: limit,
 			skip: offset,
 			sort: {
-				repost_count: -1,
+				repostCount: -1,
 				_id: -1
 			}
 		});
diff --git a/src/api/endpoints/stats.ts b/src/api/endpoints/stats.ts
index eee6f48706..719792d40d 100644
--- a/src/api/endpoints/stats.ts
+++ b/src/api/endpoints/stats.ts
@@ -18,7 +18,7 @@ import User from '../models/user';
  *             postsCount:
  *               description: count of all posts of misskey
  *               type: number
- *             users_count:
+ *             usersCount:
  *               description: count of all users of misskey
  *               type: number
  *
@@ -43,6 +43,6 @@ module.exports = params => new Promise(async (res, rej) => {
 
 	res({
 		postsCount: postsCount,
-		users_count: usersCount
+		usersCount: usersCount
 	});
 });
diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts
index 9ece429b60..9346907492 100644
--- a/src/api/endpoints/users/posts.ts
+++ b/src/api/endpoints/users/posts.ts
@@ -34,13 +34,13 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 		return rej('userId or pair of username and host is required');
 	}
 
-	// Get 'include_replies' parameter
-	const [includeReplies = true, includeRepliesErr] = $(params.include_replies).optional.boolean().$;
-	if (includeRepliesErr) return rej('invalid include_replies param');
+	// Get 'includeReplies' parameter
+	const [includeReplies = true, includeRepliesErr] = $(params.includeReplies).optional.boolean().$;
+	if (includeRepliesErr) return rej('invalid includeReplies param');
 
-	// Get 'with_media' parameter
-	const [withMedia = false, withMediaErr] = $(params.with_media).optional.boolean().$;
-	if (withMediaErr) return rej('invalid with_media param');
+	// Get 'withMedia' parameter
+	const [withMedia = false, withMediaErr] = $(params.withMedia).optional.boolean().$;
+	if (withMediaErr) return rej('invalid withMedia param');
 
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
diff --git a/src/api/models/app.ts b/src/api/models/app.ts
index 20af049b27..528ab156f1 100644
--- a/src/api/models/app.ts
+++ b/src/api/models/app.ts
@@ -96,7 +96,7 @@ export const pack = (
 				limit: 1
 			});
 
-		_app.is_authorized = exist === 1;
+		_app.isAuthorized = exist === 1;
 	}
 
 	resolve(_app);
diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts
index aab21db070..1c7c52a34e 100644
--- a/src/api/models/channel.ts
+++ b/src/api/models/channel.ts
@@ -67,7 +67,7 @@ export const pack = (
 			deletedAt: { $exists: false }
 		});
 
-		_channel.is_watching = watch !== null;
+		_channel.isWatching = watch !== null;
 		//#endregion
 	}
 
diff --git a/src/api/models/drive-folder.ts b/src/api/models/drive-folder.ts
index 52f784e069..958e3fb9ef 100644
--- a/src/api/models/drive-folder.ts
+++ b/src/api/models/drive-folder.ts
@@ -62,8 +62,8 @@ export const pack = (
 			'metadata.folderId': _folder.id
 		});
 
-		_folder.folders_count = childFoldersCount;
-		_folder.files_count = childFilesCount;
+		_folder.foldersCount = childFoldersCount;
+		_folder.filesCount = childFilesCount;
 	}
 
 	if (opts.detail && _folder.parentId) {
diff --git a/src/api/models/post.ts b/src/api/models/post.ts
index 4ab840b5ed..4f7729fbe8 100644
--- a/src/api/models/post.ts
+++ b/src/api/models/post.ts
@@ -30,6 +30,10 @@ export type IPost = {
 	userId: mongo.ObjectID;
 	appId: mongo.ObjectID;
 	viaMobile: boolean;
+	repostCount: number;
+	repliesCount: number;
+	reactionCounts: any;
+	mentions: mongo.ObjectID[];
 	geo: {
 		latitude: number;
 		longitude: number;
@@ -184,7 +188,7 @@ export const pack = async (
 					const myChoice = poll.choices
 						.filter(c => c.id == vote.choice)[0];
 
-					myChoice.is_voted = true;
+					myChoice.isVoted = true;
 				}
 
 				return poll;
diff --git a/src/api/models/user.ts b/src/api/models/user.ts
index 9ee413e0d8..0cf0fe0bdb 100644
--- a/src/api/models/user.ts
+++ b/src/api/models/user.ts
@@ -88,7 +88,7 @@ export type IUser = {
 	bannerId: mongo.ObjectID;
 	data: any;
 	description: string;
-	latest_post: IPost;
+	latestPost: IPost;
 	pinnedPostId: mongo.ObjectID;
 	isSuspended: boolean;
 	keywords: string[];
@@ -167,7 +167,7 @@ export const pack = (
 	delete _user._id;
 
 	// Remove needless properties
-	delete _user.latest_post;
+	delete _user.latestPost;
 
 	if (!_user.host) {
 		// Remove private properties
@@ -212,7 +212,7 @@ export const pack = (
 
 	if (meId && !meId.equals(_user.id)) {
 		// Whether the user is following
-		_user.is_following = (async () => {
+		_user.isFollowing = (async () => {
 			const follow = await Following.findOne({
 				followerId: meId,
 				followeeId: _user.id,
@@ -222,7 +222,7 @@ export const pack = (
 		})();
 
 		// Whether the user is followed
-		_user.is_followed = (async () => {
+		_user.isFollowed = (async () => {
 			const follow2 = await Following.findOne({
 				followerId: _user.id,
 				followeeId: meId,
@@ -232,7 +232,7 @@ export const pack = (
 		})();
 
 		// Whether the user is muted
-		_user.is_muted = (async () => {
+		_user.isMuted = (async () => {
 			const mute = await Mute.findOne({
 				muterId: meId,
 				muteeId: _user.id,
@@ -254,14 +254,14 @@ export const pack = (
 			const myFollowingIds = await getFriends(meId);
 
 			// Get following you know count
-			_user.following_you_know_count = Following.count({
+			_user.followingYouKnowCount = Following.count({
 				followeeId: { $in: myFollowingIds },
 				followerId: _user.id,
 				deletedAt: { $exists: false }
 			});
 
 			// Get followers you know count
-			_user.followers_you_know_count = Following.count({
+			_user.followersYouKnowCount = Following.count({
 				followeeId: _user.id,
 				followerId: { $in: myFollowingIds },
 				deletedAt: { $exists: false }
diff --git a/src/web/app/auth/views/index.vue b/src/web/app/auth/views/index.vue
index 690cc4f28e..e1e1b265e1 100644
--- a/src/web/app/auth/views/index.vue
+++ b/src/web/app/auth/views/index.vue
@@ -14,7 +14,7 @@
 			<p>このアプリがあなたのアカウントにアクセスすることはありません。</p>
 		</div>
 		<div class="accepted" v-if="state == 'accepted'">
-			<h1>{{ session.app.is_authorized ? 'このアプリは既に連携済みです' : 'アプリケーションの連携を許可しました'}}</h1>
+			<h1>{{ session.app.isAuthorized ? 'このアプリは既に連携済みです' : 'アプリケーションの連携を許可しました' }}</h1>
 			<p v-if="session.app.callbackUrl">アプリケーションに戻っています<mk-ellipsis/></p>
 			<p v-if="!session.app.callbackUrl">アプリケーションに戻って、やっていってください。</p>
 		</div>
@@ -61,7 +61,7 @@ export default Vue.extend({
 			this.fetching = false;
 
 			// 既に連携していた場合
-			if (this.session.app.is_authorized) {
+			if (this.session.app.isAuthorized) {
 				this.$root.$data.os.api('auth/accept', {
 					token: this.session.token
 				}).then(() => {
diff --git a/src/web/app/ch/tags/channel.tag b/src/web/app/ch/tags/channel.tag
index 225129088d..2abfb106a5 100644
--- a/src/web/app/ch/tags/channel.tag
+++ b/src/web/app/ch/tags/channel.tag
@@ -5,8 +5,8 @@
 		<h1>{ channel.title }</h1>
 
 		<div v-if="$root.$data.os.isSignedIn">
-			<p v-if="channel.is_watching">このチャンネルをウォッチしています <a @click="unwatch">ウォッチ解除</a></p>
-			<p v-if="!channel.is_watching"><a @click="watch">このチャンネルをウォッチする</a></p>
+			<p v-if="channel.isWatching">このチャンネルをウォッチしています <a @click="unwatch">ウォッチ解除</a></p>
+			<p v-if="!channel.isWatching"><a @click="watch">このチャンネルをウォッチする</a></p>
 		</div>
 
 		<div class="share">
@@ -142,7 +142,7 @@
 			this.$root.$data.os.api('channels/watch', {
 				channelId: this.id
 			}).then(() => {
-				this.channel.is_watching = true;
+				this.channel.isWatching = true;
 				this.update();
 			}, e => {
 				alert('error');
@@ -153,7 +153,7 @@
 			this.$root.$data.os.api('channels/unwatch', {
 				channelId: this.id
 			}).then(() => {
-				this.channel.is_watching = false;
+				this.channel.isWatching = false;
 				this.update();
 			}, e => {
 				alert('error');
diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts
index 512791ecb0..81444c8b01 100644
--- a/src/web/app/common/scripts/parse-search-query.ts
+++ b/src/web/app/common/scripts/parse-search-query.ts
@@ -8,10 +8,10 @@ export default function(qs: string) {
 			const [key, value] = x.split(':');
 			switch (key) {
 				case 'user':
-					q['include_user_usernames'] = value.split(',');
+					q['includeUserUsernames'] = value.split(',');
 					break;
 				case 'exclude_user':
-					q['exclude_user_usernames'] = value.split(',');
+					q['exclude_userUsernames'] = value.split(',');
 					break;
 				case 'follow':
 					q['following'] = value == 'null' ? null : value == 'true';
diff --git a/src/web/app/common/views/components/messaging-room.message.vue b/src/web/app/common/views/components/messaging-room.message.vue
index 8d35b50391..94f87fd709 100644
--- a/src/web/app/common/views/components/messaging-room.message.vue
+++ b/src/web/app/common/views/components/messaging-room.message.vue
@@ -9,7 +9,7 @@
 			<button class="delete-button" v-if="isMe" title="%i18n:common.delete%">
 				<img src="/assets/desktop/messaging/delete.png" alt="Delete"/>
 			</button>
-			<div class="content" v-if="!message.is_deleted">
+			<div class="content" v-if="!message.isDeleted">
 				<mk-post-html class="text" v-if="message.ast" :ast="message.ast" :i="os.i"/>
 				<div class="file" v-if="message.file">
 					<a :href="message.file.url" target="_blank" :title="message.file.name">
@@ -18,7 +18,7 @@
 					</a>
 				</div>
 			</div>
-			<div class="content" v-if="message.is_deleted">
+			<div class="content" v-if="message.isDeleted">
 				<p class="is-deleted">%i18n:common.tags.mk-messaging-message.deleted%</p>
 			</div>
 		</div>
diff --git a/src/web/app/common/views/components/othello.vue b/src/web/app/common/views/components/othello.vue
index 7737d74ded..8f7d9dfd6a 100644
--- a/src/web/app/common/views/components/othello.vue
+++ b/src/web/app/common/views/components/othello.vue
@@ -133,7 +133,7 @@ export default Vue.extend({
 	methods: {
 		go(game) {
 			(this as any).api('othello/games/show', {
-				game_id: game.id
+				gameId: game.id
 			}).then(game => {
 				this.matching = null;
 				this.game = game;
diff --git a/src/web/app/common/views/components/poll.vue b/src/web/app/common/views/components/poll.vue
index e46e89f55d..711d89720e 100644
--- a/src/web/app/common/views/components/poll.vue
+++ b/src/web/app/common/views/components/poll.vue
@@ -4,7 +4,7 @@
 		<li v-for="choice in poll.choices" :key="choice.id" @click="vote(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:common.tags.mk-poll.vote-to%'.replace('{}', choice.text) : ''">
 			<div class="backdrop" :style="{ 'width': (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div>
 			<span>
-				<template v-if="choice.is_voted">%fa:check%</template>
+				<template v-if="choice.isVoted">%fa:check%</template>
 				<span>{{ choice.text }}</span>
 				<span class="votes" v-if="showResult">({{ '%i18n:common.tags.mk-poll.vote-count%'.replace('{}', choice.votes) }})</span>
 			</span>
@@ -36,7 +36,7 @@ export default Vue.extend({
 			return this.poll.choices.reduce((a, b) => a + b.votes, 0);
 		},
 		isVoted(): boolean {
-			return this.poll.choices.some(c => c.is_voted);
+			return this.poll.choices.some(c => c.isVoted);
 		}
 	},
 	created() {
@@ -47,7 +47,7 @@ export default Vue.extend({
 			this.showResult = !this.showResult;
 		},
 		vote(id) {
-			if (this.poll.choices.some(c => c.is_voted)) return;
+			if (this.poll.choices.some(c => c.isVoted)) return;
 			(this as any).api('posts/polls/vote', {
 				postId: this.post.id,
 				choice: id
@@ -55,7 +55,7 @@ export default Vue.extend({
 				this.poll.choices.forEach(c => {
 					if (c.id == id) {
 						c.votes++;
-						Vue.set(c, 'is_voted', true);
+						Vue.set(c, 'isVoted', true);
 					}
 				});
 				this.showResult = true;
diff --git a/src/web/app/common/views/components/reactions-viewer.vue b/src/web/app/common/views/components/reactions-viewer.vue
index f6a27d9139..246451008f 100644
--- a/src/web/app/common/views/components/reactions-viewer.vue
+++ b/src/web/app/common/views/components/reactions-viewer.vue
@@ -20,7 +20,7 @@ export default Vue.extend({
 	props: ['post'],
 	computed: {
 		reactions(): number {
-			return this.post.reaction_counts;
+			return this.post.reactionCounts;
 		}
 	}
 });
diff --git a/src/web/app/desktop/views/components/follow-button.vue b/src/web/app/desktop/views/components/follow-button.vue
index 01b7e2aefd..9eb22b0fb8 100644
--- a/src/web/app/desktop/views/components/follow-button.vue
+++ b/src/web/app/desktop/views/components/follow-button.vue
@@ -1,15 +1,15 @@
 <template>
 <button class="mk-follow-button"
-	:class="{ wait, follow: !user.is_following, unfollow: user.is_following, big: size == 'big' }"
+	:class="{ wait, follow: !user.isFollowing, unfollow: user.isFollowing, big: size == 'big' }"
 	@click="onClick"
 	:disabled="wait"
-	:title="user.is_following ? 'フォロー解除' : 'フォローする'"
+	:title="user.isFollowing ? 'フォロー解除' : 'フォローする'"
 >
-	<template v-if="!wait && user.is_following">
+	<template v-if="!wait && user.isFollowing">
 		<template v-if="size == 'compact'">%fa:minus%</template>
 		<template v-if="size == 'big'">%fa:minus%フォロー解除</template>
 	</template>
-	<template v-if="!wait && !user.is_following">
+	<template v-if="!wait && !user.isFollowing">
 		<template v-if="size == 'compact'">%fa:plus%</template>
 		<template v-if="size == 'big'">%fa:plus%フォロー</template>
 	</template>
@@ -53,23 +53,23 @@ export default Vue.extend({
 
 		onFollow(user) {
 			if (user.id == this.user.id) {
-				this.user.is_following = user.is_following;
+				this.user.isFollowing = user.isFollowing;
 			}
 		},
 
 		onUnfollow(user) {
 			if (user.id == this.user.id) {
-				this.user.is_following = user.is_following;
+				this.user.isFollowing = user.isFollowing;
 			}
 		},
 
 		onClick() {
 			this.wait = true;
-			if (this.user.is_following) {
+			if (this.user.isFollowing) {
 				(this as any).api('following/delete', {
 					userId: this.user.id
 				}).then(() => {
-					this.user.is_following = false;
+					this.user.isFollowing = false;
 				}).catch(err => {
 					console.error(err);
 				}).then(() => {
@@ -79,7 +79,7 @@ export default Vue.extend({
 				(this as any).api('following/create', {
 					userId: this.user.id
 				}).then(() => {
-					this.user.is_following = true;
+					this.user.isFollowing = true;
 				}).catch(err => {
 					console.error(err);
 				}).then(() => {
diff --git a/src/web/app/desktop/views/components/followers.vue b/src/web/app/desktop/views/components/followers.vue
index e8330289ca..a1b98995d8 100644
--- a/src/web/app/desktop/views/components/followers.vue
+++ b/src/web/app/desktop/views/components/followers.vue
@@ -2,7 +2,7 @@
 <mk-users-list
 	:fetch="fetch"
 	:count="user.followersCount"
-	:you-know-count="user.followers_you_know_count"
+	:you-know-count="user.followersYouKnowCount"
 >
 	フォロワーはいないようです。
 </mk-users-list>
diff --git a/src/web/app/desktop/views/components/following.vue b/src/web/app/desktop/views/components/following.vue
index 0dab6ac7b3..b7aedda84f 100644
--- a/src/web/app/desktop/views/components/following.vue
+++ b/src/web/app/desktop/views/components/following.vue
@@ -2,7 +2,7 @@
 <mk-users-list
 	:fetch="fetch"
 	:count="user.followingCount"
-	:you-know-count="user.following_you_know_count"
+	:you-know-count="user.followingYouKnowCount"
 >
 	フォロー中のユーザーはいないようです。
 </mk-users-list>
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index 611660f523..3f62c0d598 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -56,10 +56,10 @@
 		<footer>
 			<mk-reactions-viewer :post="p"/>
 			<button @click="reply" title="返信">
-				%fa:reply%<p class="count" v-if="p.replies_count > 0">{{ p.replies_count }}</p>
+				%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
 			</button>
 			<button @click="repost" title="Repost">
-				%fa:retweet%<p class="count" v-if="p.repost_count > 0">{{ p.repost_count }}</p>
+				%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 			</button>
 			<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="リアクション">
 				%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
@@ -122,9 +122,9 @@ export default Vue.extend({
 			return this.isRepost ? this.post.repost : this.post;
 		},
 		reactionsCount(): number {
-			return this.p.reaction_counts
-				? Object.keys(this.p.reaction_counts)
-					.map(key => this.p.reaction_counts[key])
+			return this.p.reactionCounts
+				? Object.keys(this.p.reactionCounts)
+					.map(key => this.p.reactionCounts[key])
 					.reduce((a, b) => a + b)
 				: 0;
 		},
diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue
index e6dff2ccda..a9b4d9eead 100644
--- a/src/web/app/desktop/views/components/posts.post.vue
+++ b/src/web/app/desktop/views/components/posts.post.vue
@@ -58,10 +58,10 @@
 			<footer>
 				<mk-reactions-viewer :post="p" ref="reactionsViewer"/>
 				<button @click="reply" title="%i18n:desktop.tags.mk-timeline-post.reply%">
-					%fa:reply%<p class="count" v-if="p.replies_count > 0">{{ p.replies_count }}</p>
+					%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
 				</button>
 				<button @click="repost" title="%i18n:desktop.tags.mk-timeline-post.repost%">
-					%fa:retweet%<p class="count" v-if="p.repost_count > 0">{{ p.repost_count }}</p>
+					%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 				</button>
 				<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="%i18n:desktop.tags.mk-timeline-post.add-reaction%">
 					%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
@@ -129,9 +129,9 @@ export default Vue.extend({
 			return this.isRepost ? this.post.repost : this.post;
 		},
 		reactionsCount(): number {
-			return this.p.reaction_counts
-				? Object.keys(this.p.reaction_counts)
-					.map(key => this.p.reaction_counts[key])
+			return this.p.reactionCounts
+				? Object.keys(this.p.reactionCounts)
+					.map(key => this.p.reactionCounts[key])
 					.reduce((a, b) => a + b)
 				: 0;
 		},
diff --git a/src/web/app/desktop/views/components/users-list.item.vue b/src/web/app/desktop/views/components/users-list.item.vue
index c2f30cf382..d2bfc117da 100644
--- a/src/web/app/desktop/views/components/users-list.item.vue
+++ b/src/web/app/desktop/views/components/users-list.item.vue
@@ -9,7 +9,7 @@
 			<span class="username">@{{ acct }}</span>
 		</header>
 		<div class="body">
-			<p class="followed" v-if="user.is_followed">フォローされています</p>
+			<p class="followed" v-if="user.isFollowed">フォローされています</p>
 			<div class="description">{{ user.description }}</div>
 		</div>
 	</div>
diff --git a/src/web/app/desktop/views/pages/othello.vue b/src/web/app/desktop/views/pages/othello.vue
index 160dd9a354..0d8e987dd9 100644
--- a/src/web/app/desktop/views/pages/othello.vue
+++ b/src/web/app/desktop/views/pages/othello.vue
@@ -34,7 +34,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('othello/games/show', {
-				game_id: this.$route.params.game
+				gameId: this.$route.params.game
 			}).then(game => {
 				this.game = game;
 				this.fetching = false;
diff --git a/src/web/app/desktop/views/pages/user/user.photos.vue b/src/web/app/desktop/views/pages/user/user.photos.vue
index 2baf042bc0..1ff79b4aee 100644
--- a/src/web/app/desktop/views/pages/user/user.photos.vue
+++ b/src/web/app/desktop/views/pages/user/user.photos.vue
@@ -24,7 +24,7 @@ export default Vue.extend({
 	mounted() {
 		(this as any).api('users/posts', {
 			userId: this.user.id,
-			with_media: true,
+			withMedia: true,
 			limit: 9
 		}).then(posts => {
 			posts.forEach(post => {
diff --git a/src/web/app/desktop/views/pages/user/user.profile.vue b/src/web/app/desktop/views/pages/user/user.profile.vue
index 0d91df2a59..f5562d0915 100644
--- a/src/web/app/desktop/views/pages/user/user.profile.vue
+++ b/src/web/app/desktop/views/pages/user/user.profile.vue
@@ -2,9 +2,9 @@
 <div class="profile">
 	<div class="friend-form" v-if="os.isSignedIn && os.i.id != user.id">
 		<mk-follow-button :user="user" size="big"/>
-		<p class="followed" v-if="user.is_followed">%i18n:desktop.tags.mk-user.follows-you%</p>
-		<p v-if="user.is_muted">%i18n:desktop.tags.mk-user.muted% <a @click="unmute">%i18n:desktop.tags.mk-user.unmute%</a></p>
-		<p v-if="!user.is_muted"><a @click="mute">%i18n:desktop.tags.mk-user.mute%</a></p>
+		<p class="followed" v-if="user.isFollowed">%i18n:desktop.tags.mk-user.follows-you%</p>
+		<p v-if="user.isMuted">%i18n:desktop.tags.mk-user.muted% <a @click="unmute">%i18n:desktop.tags.mk-user.unmute%</a></p>
+		<p v-if="!user.isMuted"><a @click="mute">%i18n:desktop.tags.mk-user.mute%</a></p>
 	</div>
 	<div class="description" v-if="user.description">{{ user.description }}</div>
 	<div class="birthday" v-if="user.host === null && user.account.profile.birthday">
@@ -51,7 +51,7 @@ export default Vue.extend({
 			(this as any).api('mute/create', {
 				userId: this.user.id
 			}).then(() => {
-				this.user.is_muted = true;
+				this.user.isMuted = true;
 			}, () => {
 				alert('error');
 			});
@@ -61,7 +61,7 @@ export default Vue.extend({
 			(this as any).api('mute/delete', {
 				userId: this.user.id
 			}).then(() => {
-				this.user.is_muted = false;
+				this.user.isMuted = false;
 			}, () => {
 				alert('error');
 			});
diff --git a/src/web/app/mobile/views/components/drive.vue b/src/web/app/mobile/views/components/drive.vue
index 5affbdaf1f..ff5366a0ad 100644
--- a/src/web/app/mobile/views/components/drive.vue
+++ b/src/web/app/mobile/views/components/drive.vue
@@ -19,10 +19,10 @@
 	<div class="browser" :class="{ fetching }" v-if="file == null">
 		<div class="info" v-if="info">
 			<p v-if="folder == null">{{ (info.usage / info.capacity * 100).toFixed(1) }}% %i18n:mobile.tags.mk-drive.used%</p>
-			<p v-if="folder != null && (folder.folders_count > 0 || folder.files_count > 0)">
-				<template v-if="folder.folders_count > 0">{{ folder.folders_count }} %i18n:mobile.tags.mk-drive.folder-count%</template>
-				<template v-if="folder.folders_count > 0 && folder.files_count > 0">%i18n:mobile.tags.mk-drive.count-separator%</template>
-				<template v-if="folder.files_count > 0">{{ folder.files_count }} %i18n:mobile.tags.mk-drive.file-count%</template>
+			<p v-if="folder != null && (folder.foldersCount > 0 || folder.filesCount > 0)">
+				<template v-if="folder.foldersCount > 0">{{ folder.foldersCount }} %i18n:mobile.tags.mk-drive.folder-count%</template>
+				<template v-if="folder.foldersCount > 0 && folder.filesCount > 0">%i18n:mobile.tags.mk-drive.count-separator%</template>
+				<template v-if="folder.filesCount > 0">{{ folder.filesCount }} %i18n:mobile.tags.mk-drive.file-count%</template>
 			</p>
 		</div>
 		<div class="folders" v-if="folders.length > 0">
diff --git a/src/web/app/mobile/views/components/follow-button.vue b/src/web/app/mobile/views/components/follow-button.vue
index 838ea404eb..43c69d4e02 100644
--- a/src/web/app/mobile/views/components/follow-button.vue
+++ b/src/web/app/mobile/views/components/follow-button.vue
@@ -1,13 +1,13 @@
 <template>
 <button class="mk-follow-button"
-	:class="{ wait: wait, follow: !user.is_following, unfollow: user.is_following }"
+	:class="{ wait: wait, follow: !user.isFollowing, unfollow: user.isFollowing }"
 	@click="onClick"
 	:disabled="wait"
 >
-	<template v-if="!wait && user.is_following">%fa:minus%</template>
-	<template v-if="!wait && !user.is_following">%fa:plus%</template>
+	<template v-if="!wait && user.isFollowing">%fa:minus%</template>
+	<template v-if="!wait && !user.isFollowing">%fa:plus%</template>
 	<template v-if="wait">%fa:spinner .pulse .fw%</template>
-	{{ user.is_following ? '%i18n:mobile.tags.mk-follow-button.unfollow%' : '%i18n:mobile.tags.mk-follow-button.follow%' }}
+	{{ user.isFollowing ? '%i18n:mobile.tags.mk-follow-button.unfollow%' : '%i18n:mobile.tags.mk-follow-button.follow%' }}
 </button>
 </template>
 
@@ -43,23 +43,23 @@ export default Vue.extend({
 
 		onFollow(user) {
 			if (user.id == this.user.id) {
-				this.user.is_following = user.is_following;
+				this.user.isFollowing = user.isFollowing;
 			}
 		},
 
 		onUnfollow(user) {
 			if (user.id == this.user.id) {
-				this.user.is_following = user.is_following;
+				this.user.isFollowing = user.isFollowing;
 			}
 		},
 
 		onClick() {
 			this.wait = true;
-			if (this.user.is_following) {
+			if (this.user.isFollowing) {
 				(this as any).api('following/delete', {
 					userId: this.user.id
 				}).then(() => {
-					this.user.is_following = false;
+					this.user.isFollowing = false;
 				}).catch(err => {
 					console.error(err);
 				}).then(() => {
@@ -69,7 +69,7 @@ export default Vue.extend({
 				(this as any).api('following/create', {
 					userId: this.user.id
 				}).then(() => {
-					this.user.is_following = true;
+					this.user.isFollowing = true;
 				}).catch(err => {
 					console.error(err);
 				}).then(() => {
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index 241782aa5f..cf51696c44 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -59,10 +59,10 @@
 		<footer>
 			<mk-reactions-viewer :post="p"/>
 			<button @click="reply" title="%i18n:mobile.tags.mk-post-detail.reply%">
-				%fa:reply%<p class="count" v-if="p.replies_count > 0">{{ p.replies_count }}</p>
+				%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
 			</button>
 			<button @click="repost" title="Repost">
-				%fa:retweet%<p class="count" v-if="p.repost_count > 0">{{ p.repost_count }}</p>
+				%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 			</button>
 			<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="%i18n:mobile.tags.mk-post-detail.reaction%">
 				%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
@@ -122,9 +122,9 @@ export default Vue.extend({
 			return this.isRepost ? this.post.repost : this.post;
 		},
 		reactionsCount(): number {
-			return this.p.reaction_counts
-				? Object.keys(this.p.reaction_counts)
-					.map(key => this.p.reaction_counts[key])
+			return this.p.reactionCounts
+				? Object.keys(this.p.reactionCounts)
+					.map(key => this.p.reactionCounts[key])
 					.reduce((a, b) => a + b)
 				: 0;
 		},
diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue
index 0c6522db86..77ca45a7f1 100644
--- a/src/web/app/mobile/views/components/post.vue
+++ b/src/web/app/mobile/views/components/post.vue
@@ -58,10 +58,10 @@
 			<footer>
 				<mk-reactions-viewer :post="p" ref="reactionsViewer"/>
 				<button @click="reply">
-					%fa:reply%<p class="count" v-if="p.replies_count > 0">{{ p.replies_count }}</p>
+					%fa:reply%<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
 				</button>
 				<button @click="repost" title="Repost">
-					%fa:retweet%<p class="count" v-if="p.repost_count > 0">{{ p.repost_count }}</p>
+					%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 				</button>
 				<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton">
 					%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
@@ -110,9 +110,9 @@ export default Vue.extend({
 			return this.isRepost ? this.post.repost : this.post;
 		},
 		reactionsCount(): number {
-			return this.p.reaction_counts
-				? Object.keys(this.p.reaction_counts)
-					.map(key => this.p.reaction_counts[key])
+			return this.p.reactionCounts
+				? Object.keys(this.p.reactionCounts)
+					.map(key => this.p.reactionCounts[key])
 					.reduce((a, b) => a + b)
 				: 0;
 		},
diff --git a/src/web/app/mobile/views/components/user-timeline.vue b/src/web/app/mobile/views/components/user-timeline.vue
index d1f771f812..bd3e3d0c87 100644
--- a/src/web/app/mobile/views/components/user-timeline.vue
+++ b/src/web/app/mobile/views/components/user-timeline.vue
@@ -34,7 +34,7 @@ export default Vue.extend({
 	mounted() {
 		(this as any).api('users/posts', {
 			userId: this.user.id,
-			with_media: this.withMedia,
+			withMedia: this.withMedia,
 			limit: limit + 1
 		}).then(posts => {
 			if (posts.length == limit + 1) {
@@ -51,7 +51,7 @@ export default Vue.extend({
 			this.moreFetching = true;
 			(this as any).api('users/posts', {
 				userId: this.user.id,
-				with_media: this.withMedia,
+				withMedia: this.withMedia,
 				limit: limit + 1,
 				untilId: this.posts[this.posts.length - 1].id
 			}).then(posts => {
diff --git a/src/web/app/mobile/views/pages/followers.vue b/src/web/app/mobile/views/pages/followers.vue
index 08a15f945a..8c058eb4e6 100644
--- a/src/web/app/mobile/views/pages/followers.vue
+++ b/src/web/app/mobile/views/pages/followers.vue
@@ -8,7 +8,7 @@
 		v-if="!fetching"
 		:fetch="fetchUsers"
 		:count="user.followersCount"
-		:you-know-count="user.followers_you_know_count"
+		:you-know-count="user.followersYouKnowCount"
 		@loaded="onLoaded"
 	>
 		%i18n:mobile.tags.mk-user-followers.no-users%
diff --git a/src/web/app/mobile/views/pages/following.vue b/src/web/app/mobile/views/pages/following.vue
index ecdaa5a586..a73c9d1710 100644
--- a/src/web/app/mobile/views/pages/following.vue
+++ b/src/web/app/mobile/views/pages/following.vue
@@ -8,7 +8,7 @@
 		v-if="!fetching"
 		:fetch="fetchUsers"
 		:count="user.followingCount"
-		:you-know-count="user.following_you_know_count"
+		:you-know-count="user.followingYouKnowCount"
 		@loaded="onLoaded"
 	>
 		%i18n:mobile.tags.mk-user-following.no-users%
diff --git a/src/web/app/mobile/views/pages/othello.vue b/src/web/app/mobile/views/pages/othello.vue
index b110bf309e..e04e583c20 100644
--- a/src/web/app/mobile/views/pages/othello.vue
+++ b/src/web/app/mobile/views/pages/othello.vue
@@ -34,7 +34,7 @@ export default Vue.extend({
 			this.fetching = true;
 
 			(this as any).api('othello/games/show', {
-				game_id: this.$route.params.game
+				gameId: this.$route.params.game
 			}).then(game => {
 				this.game = game;
 				this.fetching = false;
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index f5bbd41625..114decb8e4 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -14,7 +14,7 @@
 				<div class="title">
 					<h1>{{ user.name }}</h1>
 					<span class="username">@{{ acct }}</span>
-					<span class="followed" v-if="user.is_followed">%i18n:mobile.tags.mk-user.follows-you%</span>
+					<span class="followed" v-if="user.isFollowed">%i18n:mobile.tags.mk-user.follows-you%</span>
 				</div>
 				<div class="description">{{ user.description }}</div>
 				<div class="info">
diff --git a/src/web/app/mobile/views/pages/user/home.photos.vue b/src/web/app/mobile/views/pages/user/home.photos.vue
index 94b5af5531..f703f8a740 100644
--- a/src/web/app/mobile/views/pages/user/home.photos.vue
+++ b/src/web/app/mobile/views/pages/user/home.photos.vue
@@ -30,7 +30,7 @@ export default Vue.extend({
 	mounted() {
 		(this as any).api('users/posts', {
 			userId: this.user.id,
-			with_media: true,
+			withMedia: true,
 			limit: 6
 		}).then(posts => {
 			posts.forEach(post => {
diff --git a/src/web/app/stats/tags/index.tag b/src/web/app/stats/tags/index.tag
index bf08c38c3a..63fdd24044 100644
--- a/src/web/app/stats/tags/index.tag
+++ b/src/web/app/stats/tags/index.tag
@@ -83,7 +83,7 @@
 </mk-posts>
 
 <mk-users>
-	<h2>%i18n:stats.users-count% <b>{ stats.users_count }</b></h2>
+	<h2>%i18n:stats.users-count% <b>{ stats.usersCount }</b></h2>
 	<mk-users-chart v-if="!initializing" data={ data }/>
 	<style lang="stylus" scoped>
 		:scope
diff --git a/src/web/docs/api/entities/post.yaml b/src/web/docs/api/entities/post.yaml
index 8a616f088b..0a07308460 100644
--- a/src/web/docs/api/entities/post.yaml
+++ b/src/web/docs/api/entities/post.yaml
@@ -59,7 +59,7 @@ props:
     desc:
       ja: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>"
       en: "The your <a href='/docs/api/reactions'>reaction</a> of this post"
-  - name: "reaction_counts"
+  - name: "reactionCounts"
     type: "object"
     optional: false
     desc:
@@ -110,7 +110,7 @@ props:
             desc:
               ja: "選択肢ID"
               en: "The ID of this choice"
-          - name: "is_voted"
+          - name: "isVoted"
             type: "boolean"
             optional: true
             desc:
diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml
index f45455e731..a1fae1482b 100644
--- a/src/web/docs/api/entities/user.yaml
+++ b/src/web/docs/api/entities/user.yaml
@@ -65,17 +65,17 @@ props:
     desc:
       ja: "フォローしているユーザーの数"
       en: "The number of the following users for this user"
-  - name: "is_following"
+  - name: "isFollowing"
     type: "boolean"
     optional: true
     desc:
       ja: "自分がこのユーザーをフォローしているか"
-  - name: "is_followed"
+  - name: "isFollowed"
     type: "boolean"
     optional: true
     desc:
       ja: "自分がこのユーザーにフォローされているか"
-  - name: "is_muted"
+  - name: "isMuted"
     type: "boolean"
     optional: true
     desc:
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/shell.camel-case.js
index afe831e5b7..8d07140ba5 100644
--- a/tools/migration/shell.camel-case.js
+++ b/tools/migration/shell.camel-case.js
@@ -176,6 +176,9 @@ db.posts.update({}, {
 		reply_id: 'replyId',
 		repost_id: 'repostId',
 		via_mobile: 'viaMobile',
+		reaction_counts: 'reactionCounts',
+		replies_count: 'repliesCount',
+		repost_count: 'repostCount',
 		'_reply.user_id': '_reply.userId',
 		'_repost.user_id': '_repost.userId',
 	}

From 63b930e9fd14f2b6ccb2c484670d27ecd7a247b0 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 17:00:28 +0900
Subject: [PATCH 23/43] wip

---
 src/api/endpoints/posts/create.ts            | 2 +-
 src/api/models/app.ts                        | 2 +-
 src/common/othello/ai/back.ts                | 2 +-
 src/web/docs/api/endpoints/posts/create.yaml | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 2817374545..34f3eea02f 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -270,7 +270,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 
 	// Reponse
 	res({
-		created_post: postObj
+		createdPost: postObj
 	});
 
 	//#region Post processes
diff --git a/src/api/models/app.ts b/src/api/models/app.ts
index 528ab156f1..6759b52cde 100644
--- a/src/api/models/app.ts
+++ b/src/api/models/app.ts
@@ -83,7 +83,7 @@ export const pack = (
 		delete _app.secret;
 	}
 
-	_app.icon_url = _app.icon != null
+	_app.iconUrl = _app.icon != null
 		? `${config.drive_url}/${_app.icon}`
 		: `${config.drive_url}/app-default.jpg`;
 
diff --git a/src/common/othello/ai/back.ts b/src/common/othello/ai/back.ts
index 52f01ff97b..0950adaa9f 100644
--- a/src/common/othello/ai/back.ts
+++ b/src/common/othello/ai/back.ts
@@ -56,7 +56,7 @@ process.on('message', async msg => {
 			}
 		});
 
-		post = res.created_post;
+		post = res.createdPost;
 		//#endregion
 	}
 
diff --git a/src/web/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml
index 70d35008c0..11d9f40c54 100644
--- a/src/web/docs/api/endpoints/posts/create.yaml
+++ b/src/web/docs/api/endpoints/posts/create.yaml
@@ -45,7 +45,7 @@ params:
           en: "Choices of a poll"
 
 res:
-  - name: "created_post"
+  - name: "createdPost"
     type: "entity(Post)"
     optional: false
     desc:

From c26b5fe05794d6f24d3db91b2acecade81984d93 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 17:02:02 +0900
Subject: [PATCH 24/43] wip

---
 src/api/endpoints/posts/search.ts                    | 12 ++++++------
 src/api/models/post.ts                               |  2 +-
 src/web/app/common/scripts/parse-search-query.ts     |  2 +-
 src/web/app/desktop/views/components/post-detail.vue |  2 +-
 src/web/app/desktop/views/components/posts.post.vue  |  2 +-
 src/web/app/mobile/views/components/post-detail.vue  |  2 +-
 src/web/app/mobile/views/components/post.vue         |  2 +-
 src/web/docs/api/entities/post.yaml                  |  2 +-
 8 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts
index 5c324bfe9a..bb5c438926 100644
--- a/src/api/endpoints/posts/search.ts
+++ b/src/api/endpoints/posts/search.ts
@@ -25,17 +25,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 	const [includeUserIds = [], includeUserIdsErr] = $(params.includeUserIds).optional.array('id').$;
 	if (includeUserIdsErr) return rej('invalid includeUserIds param');
 
-	// Get 'exclude_userIds' parameter
-	const [excludeUserIds = [], excludeUserIdsErr] = $(params.exclude_userIds).optional.array('id').$;
-	if (excludeUserIdsErr) return rej('invalid exclude_userIds param');
+	// Get 'excludeUserIds' parameter
+	const [excludeUserIds = [], excludeUserIdsErr] = $(params.excludeUserIds).optional.array('id').$;
+	if (excludeUserIdsErr) return rej('invalid excludeUserIds param');
 
 	// Get 'includeUserUsernames' parameter
 	const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.includeUserUsernames).optional.array('string').$;
 	if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param');
 
-	// Get 'exclude_userUsernames' parameter
-	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.exclude_userUsernames).optional.array('string').$;
-	if (excludeUserUsernamesErr) return rej('invalid exclude_userUsernames param');
+	// Get 'excludeUserUsernames' parameter
+	const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.excludeUserUsernames).optional.array('string').$;
+	if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param');
 
 	// Get 'following' parameter
 	const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$;
diff --git a/src/api/models/post.ts b/src/api/models/post.ts
index 4f7729fbe8..7a93753f74 100644
--- a/src/api/models/post.ts
+++ b/src/api/models/post.ts
@@ -197,7 +197,7 @@ export const pack = async (
 
 		// Fetch my reaction
 		if (meId) {
-			_post.my_reaction = (async () => {
+			_post.myReaction = (async () => {
 				const reaction = await Reaction
 					.findOne({
 						userId: meId,
diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts
index 81444c8b01..4f09d2b93f 100644
--- a/src/web/app/common/scripts/parse-search-query.ts
+++ b/src/web/app/common/scripts/parse-search-query.ts
@@ -11,7 +11,7 @@ export default function(qs: string) {
 					q['includeUserUsernames'] = value.split(',');
 					break;
 				case 'exclude_user':
-					q['exclude_userUsernames'] = value.split(',');
+					q['excludeUserUsernames'] = value.split(',');
 					break;
 				case 'follow':
 					q['following'] = value == 'null' ? null : value == 'true';
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index 3f62c0d598..7783ec62c7 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -61,7 +61,7 @@
 			<button @click="repost" title="Repost">
 				%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 			</button>
-			<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="リアクション">
+			<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="リアクション">
 				%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
 			</button>
 			<button @click="menu" ref="menuButton">
diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue
index a9b4d9eead..c70e019115 100644
--- a/src/web/app/desktop/views/components/posts.post.vue
+++ b/src/web/app/desktop/views/components/posts.post.vue
@@ -63,7 +63,7 @@
 				<button @click="repost" title="%i18n:desktop.tags.mk-timeline-post.repost%">
 					%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 				</button>
-				<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="%i18n:desktop.tags.mk-timeline-post.add-reaction%">
+				<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:desktop.tags.mk-timeline-post.add-reaction%">
 					%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
 				</button>
 				<button @click="menu" ref="menuButton">
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index cf51696c44..29993c79ed 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -64,7 +64,7 @@
 			<button @click="repost" title="Repost">
 				%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 			</button>
-			<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="%i18n:mobile.tags.mk-post-detail.reaction%">
+			<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:mobile.tags.mk-post-detail.reaction%">
 				%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
 			</button>
 			<button @click="menu" ref="menuButton">
diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue
index 77ca45a7f1..66c595f4e9 100644
--- a/src/web/app/mobile/views/components/post.vue
+++ b/src/web/app/mobile/views/components/post.vue
@@ -63,7 +63,7 @@
 				<button @click="repost" title="Repost">
 					%fa:retweet%<p class="count" v-if="p.repostCount > 0">{{ p.repostCount }}</p>
 				</button>
-				<button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton">
+				<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton">
 					%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
 				</button>
 				<button class="menu" @click="menu" ref="menuButton">
diff --git a/src/web/docs/api/entities/post.yaml b/src/web/docs/api/entities/post.yaml
index 0a07308460..71b6a64123 100644
--- a/src/web/docs/api/entities/post.yaml
+++ b/src/web/docs/api/entities/post.yaml
@@ -53,7 +53,7 @@ props:
     desc:
       ja: "投稿者"
       en: "The author of this post"
-  - name: "my_reaction"
+  - name: "myReaction"
     type: "string"
     optional: true
     desc:

From a42e8efb6677dc52ee688e5038efb4c1eca7a72a Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 17:03:32 +0900
Subject: [PATCH 25/43] oops

---
 src/api/common/add-file-to-drive.ts | 306 ----------------------------
 1 file changed, 306 deletions(-)
 delete mode 100644 src/api/common/add-file-to-drive.ts

diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts
deleted file mode 100644
index 6bf5fcbc02..0000000000
--- a/src/api/common/add-file-to-drive.ts
+++ /dev/null
@@ -1,306 +0,0 @@
-import { Buffer } from 'buffer';
-import * as fs from 'fs';
-import * as tmp from 'tmp';
-import * as stream from 'stream';
-
-import * as mongodb from 'mongodb';
-import * as crypto from 'crypto';
-import * as _gm from 'gm';
-import * as debug from 'debug';
-import fileType = require('file-type');
-import prominence = require('prominence');
-
-import DriveFile, { getGridFSBucket } from '../models/drive-file';
-import DriveFolder from '../models/drive-folder';
-import { pack } from '../models/drive-file';
-import event, { publishDriveStream } from '../event';
-import config from '../../conf';
-
-const gm = _gm.subClass({
-	imageMagick: true
-});
-
-const log = debug('misskey:register-drive-file');
-
-const tmpFile = (): Promise<string> => new Promise((resolve, reject) => {
-	tmp.file((e, path) => {
-		if (e) return reject(e);
-		resolve(path);
-	});
-});
-
-const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise<any> =>
-	getGridFSBucket()
-		.then(bucket => new Promise((resolve, reject) => {
-			const writeStream = bucket.openUploadStream(name, { contentType: type, metadata });
-			writeStream.once('finish', (doc) => { resolve(doc); });
-			writeStream.on('error', reject);
-			readable.pipe(writeStream);
-		}));
-
-const addFile = async (
-	user: any,
-	path: string,
-	name: string = null,
-	comment: string = null,
-	folderId: mongodb.ObjectID = null,
-	force: boolean = false
-) => {
-	log(`registering ${name} (user: ${user.username}, path: ${path})`);
-
-	// Calculate hash, get content type and get file size
-	const [hash, [mime, ext], size] = await Promise.all([
-		// hash
-		((): Promise<string> => new Promise((res, rej) => {
-			const readable = fs.createReadStream(path);
-			const hash = crypto.createHash('md5');
-			const chunks = [];
-			readable
-				.on('error', rej)
-				.pipe(hash)
-				.on('error', rej)
-				.on('data', (chunk) => chunks.push(chunk))
-				.on('end', () => {
-					const buffer = Buffer.concat(chunks);
-					res(buffer.toString('hex'));
-				});
-		}))(),
-		// mime
-		((): Promise<[string, string | null]> => new Promise((res, rej) => {
-			const readable = fs.createReadStream(path);
-			readable
-				.on('error', rej)
-				.once('data', (buffer: Buffer) => {
-					readable.destroy();
-					const type = fileType(buffer);
-					if (type) {
-						return res([type.mime, type.ext]);
-					} else {
-						// 種類が同定できなかったら application/octet-stream にする
-						return res(['application/octet-stream', null]);
-					}
-				});
-		}))(),
-		// size
-		((): Promise<number> => new Promise((res, rej) => {
-			fs.stat(path, (err, stats) => {
-				if (err) return rej(err);
-				res(stats.size);
-			});
-		}))()
-	]);
-
-	log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`);
-
-	// detect name
-	const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled');
-
-	if (!force) {
-		// Check if there is a file with the same hash
-		const much = await DriveFile.findOne({
-			md5: hash,
-			'metadata.userId': user._id
-		});
-
-		if (much !== null) {
-			log('file with same hash is found');
-			return much;
-		} else {
-			log('file with same hash is not found');
-		}
-	}
-
-	const [wh, avgColor, folder] = await Promise.all([
-		// Width and height (when image)
-		(async () => {
-			// 画像かどうか
-			if (!/^image\/.*$/.test(mime)) {
-				return null;
-			}
-
-			const imageType = mime.split('/')[1];
-
-			// 画像でもPNGかJPEGかGIFでないならスキップ
-			if (imageType != 'png' && imageType != 'jpeg' && imageType != 'gif') {
-				return null;
-			}
-
-			log('calculate image width and height...');
-
-			// Calculate width and height
-			const g = gm(fs.createReadStream(path), name);
-			const size = await prominence(g).size();
-
-			log(`image width and height is calculated: ${size.width}, ${size.height}`);
-
-			return [size.width, size.height];
-		})(),
-		// average color (when image)
-		(async () => {
-			// 画像かどうか
-			if (!/^image\/.*$/.test(mime)) {
-				return null;
-			}
-
-			const imageType = mime.split('/')[1];
-
-			// 画像でもPNGかJPEGでないならスキップ
-			if (imageType != 'png' && imageType != 'jpeg') {
-				return null;
-			}
-
-			log('calculate average color...');
-
-			const buffer = await prominence(gm(fs.createReadStream(path), name)
-				.setFormat('ppm')
-				.resize(1, 1)) // 1pxのサイズに縮小して平均色を取得するというハック
-				.toBuffer();
-
-			const r = buffer.readUInt8(buffer.length - 3);
-			const g = buffer.readUInt8(buffer.length - 2);
-			const b = buffer.readUInt8(buffer.length - 1);
-
-			log(`average color is calculated: ${r}, ${g}, ${b}`);
-
-			return [r, g, b];
-		})(),
-		// folder
-		(async () => {
-			if (!folderId) {
-				return null;
-			}
-			const driveFolder = await DriveFolder.findOne({
-				_id: folderId,
-				userId: user._id
-			});
-			if (!driveFolder) {
-				throw 'folder-not-found';
-			}
-			return driveFolder;
-		})(),
-		// usage checker
-		(async () => {
-			// Calculate drive usage
-			const usage = await DriveFile
-				.aggregate([{
-					$match: { 'metadata.userId': user._id }
-				}, {
-					$project: {
-						length: true
-					}
-				}, {
-					$group: {
-						_id: null,
-						usage: { $sum: '$length' }
-					}
-				}])
-				.then((aggregates: any[]) => {
-					if (aggregates.length > 0) {
-						return aggregates[0].usage;
-					}
-					return 0;
-				});
-
-			log(`drive usage is ${usage}`);
-
-			// If usage limit exceeded
-			if (usage + size > user.driveCapacity) {
-				throw 'no-free-space';
-			}
-		})()
-	]);
-
-	const readable = fs.createReadStream(path);
-
-	const properties = {};
-
-	if (wh) {
-		properties['width'] = wh[0];
-		properties['height'] = wh[1];
-	}
-
-	if (avgColor) {
-		properties['avgColor'] = avgColor;
-	}
-
-	return addToGridFS(detectedName, readable, mime, {
-		userId: user._id,
-		folderId: folder !== null ? folder._id : null,
-		comment: comment,
-		properties: properties
-	});
-};
-
-/**
- * Add file to drive
- *
- * @param user User who wish to add file
- * @param file File path or readableStream
- * @param comment Comment
- * @param type File type
- * @param folderId Folder ID
- * @param force If set to true, forcibly upload the file even if there is a file with the same hash.
- * @return Object that represents added file
- */
-export default (user: any, file: string | stream.Readable, ...args) => new Promise<any>((resolve, reject) => {
-	// Get file path
-	new Promise((res: (v: [string, boolean]) => void, rej) => {
-		if (typeof file === 'string') {
-			res([file, false]);
-			return;
-		}
-		if (typeof file === 'object' && typeof file.read === 'function') {
-			tmpFile()
-				.then(path => {
-					const readable: stream.Readable = file;
-					const writable = fs.createWriteStream(path);
-					readable
-						.on('error', rej)
-						.on('end', () => {
-							res([path, true]);
-						})
-						.pipe(writable)
-						.on('error', rej);
-				})
-				.catch(rej);
-		}
-		rej(new Error('un-compatible file.'));
-	})
-	.then(([path, shouldCleanup]): Promise<any> => new Promise((res, rej) => {
-		addFile(user, path, ...args)
-			.then(file => {
-				res(file);
-				if (shouldCleanup) {
-					fs.unlink(path, (e) => {
-						if (e) log(e.stack);
-					});
-				}
-			})
-			.catch(rej);
-	}))
-	.then(file => {
-		log(`drive file has been created ${file._id}`);
-		resolve(file);
-
-		pack(file).then(serializedFile => {
-			// Publish drive_file_created event
-			event(user._id, 'drive_file_created', serializedFile);
-			publishDriveStream(user._id, 'file_created', serializedFile);
-
-			// Register to search database
-			if (config.elasticsearch.enable) {
-				const es = require('../../db/elasticsearch');
-				es.index({
-					index: 'misskey',
-					type: 'drive_file',
-					id: file._id.toString(),
-					body: {
-						name: file.name,
-						userId: user._id.toString()
-					}
-				});
-			}
-		});
-	})
-	.catch(reject);
-});

From 64f69979100e1bb856bd8cd44f5df20d54c124f8 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 18:43:49 +0900
Subject: [PATCH 26/43] =?UTF-8?q?=E8=89=AF=E3=81=84=E6=84=9F=E3=81=98?=
 =?UTF-8?q?=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../1.js}                                     |  3 +-
 .../2.js}                                     |  3 +-
 tools/migration/nighthike/3.js                | 73 +++++++++++++++++++
 .../{shell.camel-case.js => nighthike/4.js}   |  0
 .../node.1522066477.user-account-keypair.js   | 39 ----------
 .../shell.1522038492.user-account.js          | 41 -----------
 tools/migration/shell.1522116709.user-host.js |  1 -
 .../shell.1522116710.user-host_lower.js       |  1 -
 8 files changed, 75 insertions(+), 86 deletions(-)
 rename tools/migration/{node.2018-03-28.username.js => nighthike/1.js} (86%)
 rename tools/migration/{node.2018-03-28.appname.js => nighthike/2.js} (86%)
 create mode 100644 tools/migration/nighthike/3.js
 rename tools/migration/{shell.camel-case.js => nighthike/4.js} (100%)
 delete mode 100644 tools/migration/node.1522066477.user-account-keypair.js
 delete mode 100644 tools/migration/shell.1522038492.user-account.js
 delete mode 100644 tools/migration/shell.1522116709.user-host.js
 delete mode 100644 tools/migration/shell.1522116710.user-host_lower.js

diff --git a/tools/migration/node.2018-03-28.username.js b/tools/migration/nighthike/1.js
similarity index 86%
rename from tools/migration/node.2018-03-28.username.js
rename to tools/migration/nighthike/1.js
index 2222152101..d7e011c5bd 100644
--- a/tools/migration/node.2018-03-28.username.js
+++ b/tools/migration/nighthike/1.js
@@ -1,7 +1,6 @@
 // for Node.js interpret
 
-const { default: User } = require('../../built/api/models/user');
-const { generate } = require('../../built/crypto_key');
+const { default: User } = require('../../../built/api/models/user');
 const { default: zip } = require('@prezzemolo/zip')
 
 const migrate = async (user) => {
diff --git a/tools/migration/node.2018-03-28.appname.js b/tools/migration/nighthike/2.js
similarity index 86%
rename from tools/migration/node.2018-03-28.appname.js
rename to tools/migration/nighthike/2.js
index 9f16e47202..8fb5bbb08d 100644
--- a/tools/migration/node.2018-03-28.appname.js
+++ b/tools/migration/nighthike/2.js
@@ -1,7 +1,6 @@
 // for Node.js interpret
 
-const { default: App } = require('../../built/api/models/app');
-const { generate } = require('../../built/crypto_key');
+const { default: App } = require('../../../built/api/models/app');
 const { default: zip } = require('@prezzemolo/zip')
 
 const migrate = async (app) => {
diff --git a/tools/migration/nighthike/3.js b/tools/migration/nighthike/3.js
new file mode 100644
index 0000000000..cc0603d9e4
--- /dev/null
+++ b/tools/migration/nighthike/3.js
@@ -0,0 +1,73 @@
+// for Node.js interpret
+
+const { default: User } = require('../../../built/api/models/user');
+const { generate } = require('../../../built/crypto_key');
+const { default: zip } = require('@prezzemolo/zip')
+
+const migrate = async (user) => {
+	const result = await User.update(user._id, {
+		$unset: {
+			email: '',
+			links: '',
+			password: '',
+			token: '',
+			twitter: '',
+			line: '',
+			profile: '',
+			last_used_at: '',
+			is_bot: '',
+			is_pro: '',
+			two_factor_secret: '',
+			two_factor_enabled: '',
+			client_settings: '',
+			settings: ''
+		},
+		$set: {
+			host: null,
+			host_lower: null,
+			account: {
+				email: user.email,
+				links: user.links,
+				password: user.password,
+				token: user.token,
+				twitter: user.twitter,
+				line: user.line,
+				profile: user.profile,
+				last_used_at: user.last_used_at,
+				is_bot: user.is_bot,
+				is_pro: user.is_pro,
+				two_factor_secret: user.two_factor_secret,
+				two_factor_enabled: user.two_factor_enabled,
+				client_settings: user.client_settings,
+				settings: user.settings,
+				keypair: generate()
+			}
+		}
+	});
+	return result.ok === 1;
+}
+
+async function main() {
+	const count = await User.count({});
+
+	const dop = Number.parseInt(process.argv[2]) || 5
+	const idop = ((count - (count % dop)) / dop) + 1
+
+	return zip(
+		1,
+		async (time) => {
+			console.log(`${time} / ${idop}`)
+			const doc = await User.find({}, {
+				limit: dop, skip: time * dop
+			})
+			return Promise.all(doc.map(migrate))
+		},
+		idop
+	).then(a => {
+		const rv = []
+		a.forEach(e => rv.push(...e))
+		return rv
+	})
+}
+
+main().then(console.dir).catch(console.error)
diff --git a/tools/migration/shell.camel-case.js b/tools/migration/nighthike/4.js
similarity index 100%
rename from tools/migration/shell.camel-case.js
rename to tools/migration/nighthike/4.js
diff --git a/tools/migration/node.1522066477.user-account-keypair.js b/tools/migration/node.1522066477.user-account-keypair.js
deleted file mode 100644
index c413e3db1e..0000000000
--- a/tools/migration/node.1522066477.user-account-keypair.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// for Node.js interpret
-
-const { default: User } = require('../../built/api/models/user');
-const { generate } = require('../../built/crypto_key');
-const { default: zip } = require('@prezzemolo/zip')
-
-const migrate = async (user) => {
-	const result = await User.update(user._id, {
-		$set: {
-			'account.keypair': generate()
-		}
-	});
-	return result.ok === 1;
-}
-
-async function main() {
-	const count = await User.count({});
-
-	const dop = Number.parseInt(process.argv[2]) || 5
-	const idop = ((count - (count % dop)) / dop) + 1
-
-	return zip(
-		1,
-		async (time) => {
-			console.log(`${time} / ${idop}`)
-			const doc = await User.find({}, {
-				limit: dop, skip: time * dop
-			})
-			return Promise.all(doc.map(migrate))
-		},
-		idop
-	).then(a => {
-		const rv = []
-		a.forEach(e => rv.push(...e))
-		return rv
-	})
-}
-
-main().then(console.dir).catch(console.error)
diff --git a/tools/migration/shell.1522038492.user-account.js b/tools/migration/shell.1522038492.user-account.js
deleted file mode 100644
index 056c29e8e1..0000000000
--- a/tools/migration/shell.1522038492.user-account.js
+++ /dev/null
@@ -1,41 +0,0 @@
-db.users.dropIndex({ token: 1 });
-
-db.users.find({}).forEach(function(user) {
-	print(user._id);
-	db.users.update({ _id: user._id }, {
-		$unset: {
-			email: '',
-			links: '',
-			password: '',
-			token: '',
-			twitter: '',
-			line: '',
-			profile: '',
-			last_used_at: '',
-			is_bot: '',
-			is_pro: '',
-			two_factor_secret: '',
-			two_factor_enabled: '',
-			client_settings: '',
-			settings: ''
-		},
-		$set: {
-			account: {
-				email: user.email,
-				links: user.links,
-				password: user.password,
-				token: user.token,
-				twitter: user.twitter,
-				line: user.line,
-				profile: user.profile,
-				last_used_at: user.last_used_at,
-				is_bot: user.is_bot,
-				is_pro: user.is_pro,
-				two_factor_secret: user.two_factor_secret,
-				two_factor_enabled: user.two_factor_enabled,
-				client_settings: user.client_settings,
-				settings: user.settings
-			}
-		}
-	}, false, false);
-});
diff --git a/tools/migration/shell.1522116709.user-host.js b/tools/migration/shell.1522116709.user-host.js
deleted file mode 100644
index b354709a61..0000000000
--- a/tools/migration/shell.1522116709.user-host.js
+++ /dev/null
@@ -1 +0,0 @@
-db.users.update({ }, { $set: { host: null } }, { multi: true });
diff --git a/tools/migration/shell.1522116710.user-host_lower.js b/tools/migration/shell.1522116710.user-host_lower.js
deleted file mode 100644
index 31ec6c468a..0000000000
--- a/tools/migration/shell.1522116710.user-host_lower.js
+++ /dev/null
@@ -1 +0,0 @@
-db.users.update({ }, { $set: { host_lower: null } }, { multi: true });

From 5d6ef4fa304bb5137c9409f1794257408d1b76c8 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 19:09:13 +0900
Subject: [PATCH 27/43] oops

---
 src/api/endpoints/i/favorites.ts | 2 +-
 src/api/models/favorite.ts       | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/api/endpoints/i/favorites.ts b/src/api/endpoints/i/favorites.ts
index 22a4399540..9f8becf218 100644
--- a/src/api/endpoints/i/favorites.ts
+++ b/src/api/endpoints/i/favorites.ts
@@ -39,6 +39,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Serialize
 	res(await Promise.all(favorites.map(async favorite =>
-		await pack(favorite.post)
+		await pack(favorite.postId)
 	)));
 });
diff --git a/src/api/models/favorite.ts b/src/api/models/favorite.ts
index 5ba55c4c9f..a21c276ff5 100644
--- a/src/api/models/favorite.ts
+++ b/src/api/models/favorite.ts
@@ -1,10 +1,10 @@
 import * as mongo from 'mongodb';
 import db from '../../db/mongodb';
 
-const Favorites = db.get<IFavorites>('favorites');
+const Favorites = db.get<IFavorite>('favorites');
 export default Favorites;
 
-export type IFavorites = {
+export type IFavorite = {
 	_id: mongo.ObjectID;
 	createdAt: Date;
 	userId: mongo.ObjectID;

From 650777634a9b6d73995b319d42ffcb4a17d08259 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 19:09:42 +0900
Subject: [PATCH 28/43] Fix bug

---
 src/api/endpoints/posts/favorites/delete.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/api/endpoints/posts/favorites/delete.ts b/src/api/endpoints/posts/favorites/delete.ts
index b1b4fcebc4..db52036ec5 100644
--- a/src/api/endpoints/posts/favorites/delete.ts
+++ b/src/api/endpoints/posts/favorites/delete.ts
@@ -37,7 +37,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}
 
 	// Delete favorite
-	await Favorite.deleteOne({
+	await Favorite.remove({
 		_id: exist._id
 	});
 

From 78de0f02aedc8e82ec2e624971e9fd267947ffc4 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 19:22:53 +0900
Subject: [PATCH 29/43] Fix bug

---
 tools/migration/nighthike/4.js | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/tools/migration/nighthike/4.js b/tools/migration/nighthike/4.js
index 8d07140ba5..2e252b7f4e 100644
--- a/tools/migration/nighthike/4.js
+++ b/tools/migration/nighthike/4.js
@@ -212,21 +212,21 @@ db.users.update({}, {
 		pinned_post_id: 'pinnedPostId',
 		is_suspended: 'isSuspended',
 		host_lower: 'hostLower',
-		'twitter.access_token': 'twitter.accessToken',
-		'twitter.access_token_secret': 'twitter.accessTokenSecret',
-		'twitter.user_id': 'twitter.userId',
-		'twitter.screen_name': 'twitter.screenName',
-		'line.user_id': 'line.userId',
-		last_used_at: 'lastUsedAt',
-		is_bot: 'isBot',
-		is_pro: 'isPro',
-		two_factor_secret: 'twoFactorSecret',
-		two_factor_enabled: 'twoFactorEnabled',
-		client_settings: 'clientSettings'
+		'account.last_used_at': 'account.lastUsedAt',
+		'account.is_bot': 'account.isBot',
+		'account.is_pro': 'account.isPro',
+		'account.two_factor_secret': 'account.twoFactorSecret',
+		'account.two_factor_enabled': 'account.twoFactorEnabled',
+		'account.client_settings': 'account.clientSettings'
 	},
 	$unset: {
 		likes_count: '',
 		liked_count: '',
-		latest_post: ''
+		latest_post: '',
+		'account.twitter.access_token': '',
+		'account.twitter.access_token_secret': '',
+		'account.twitter.user_id': '',
+		'account.twitter.screen_name': '',
+		'account.line.user_id': ''
 	}
 }, false, true);

From de0013652587d3f382f1fc5bdf7e945e33ce736c Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 22:07:11 +0900
Subject: [PATCH 30/43] :v:

---
 CHANGELOG.md | 532 ---------------------------------------------------
 README.md    |   4 -
 2 files changed, 536 deletions(-)
 delete mode 100644 CHANGELOG.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 6e69a7319e..0000000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,532 +0,0 @@
-ChangeLog (Release Notes)
-=========================
-主に notable な changes を書いていきます
-
-3493 (2018/01/01)
------------------
-* なんか
-
-3460 (2017/12/23)
------------------
-* 検索で複数のユーザーを指定できるように
-* 検索でユーザーを除外できるように
-* など
-
-3451 (2017/12/22)
------------------
-* ミュート機能
-
-3430 (2017/12/21)
------------------
-* oops
-
-3428 (2017/12/21)
------------------
-* バグ修正
-
-3426 (2017/12/21)
------------------
-* 検索にpoll追加
-
-3424 (2017/12/21)
------------------
-* 検索にrepost追加
-* など
-
-3422 (2017/12/21)
------------------
-* 検索にfollow追加 #1023
-
-3420 (2017/12/21)
------------------
-* 検索機能を大幅に強化
-
-3415 (2017/12/19)
------------------
-* デザインの調整
-
-3404 (2017/12/17)
------------------
-* なんか
-
-3400 (2017/12/17)
------------------
-* なんか
-
-3392 (2017/12/17)
------------------
-* ドキュメントなど
-
-3390 (2017/12/16)
------------------
-* ドキュメントなど
-
-3347 (2017/12/11)
------------------
-* バグ修正
-
-3342 (2017/12/11)
------------------
-* なんか
-
-3339 (2017/12/11)
------------------
-* なんか
-
-3334 (2017/12/10)
------------------
-* いい感じにした
-
-3322 (2017/12/10)
------------------
-* :art:
-
-3320 (2017/12/10)
------------------
-* なんか
-
-3310 (2017/12/09)
------------------
-* i18nなど
-
-3308 (2017/12/09)
------------------
-* :art:
-
-3294 (2017/12/09)
------------------
-* バグ修正
-
-3292 (2017/12/09)
------------------
-* ユーザビリティの向上
-
-3281 (2017/12/08)
------------------
-* 二段階認証の実装 (#967)
-
-3278 (2017/12/08)
------------------
-* :v:
-
-3272 (2017/12/08)
------------------
-* Fix bug
-
-3268 (2017/12/08)
------------------
-* :v:
-
-3263 (2017/12/08)
------------------
-* FontAwesome5に移行
-
-3230 (2017/11/28)
------------------
-* :v:
-
-3219 (2017/11/28)
------------------
-* なんか
-
-3212 (2017/11/27)
------------------
-* なんか
-
-3201 (2017/11/23)
------------------
-* Twitterログインを実装 (#939)
-
-3196 (2017/11/23)
------------------
-* バグ修正
-
-3194 (2017/11/23)
------------------
-* バグ修正
-
-3191 (2017/11/23)
------------------
-* :v:
-
-3188 (2017/11/22)
------------------
-* バグ修正
-
-3180 (2017/11/21)
------------------
-* バグ修正
-
-3177 (2017/11/21)
------------------
-* ServiceWorker support
-  * Misskeyを開いていないときでも通知を受け取れるように(Chromeのみ)
-
-3165 (2017/11/20)
------------------
-* デスクトップ版でも通知バッジを表示 (#918)
-* デザインの調整
-* バグ修正
-
-3155 (2017/11/20)
------------------
-* デスクトップ版でユーザーの投稿グラフを見れるように
-
-3142 (2017/11/18)
------------------
-* バグ修正
-
-3140 (2017/11/18)
------------------
-* ウィジェットをスクロールに追従させるように
-
-3136 (2017/11/17)
------------------
-* バグ修正
-* 通信の最適化
-
-3131 (2017/11/17)
------------------
-* バグ修正
-* 通信の最適化
-
-3124 (2017/11/16)
------------------
-* バグ修正
-
-3121 (2017/11/16)
------------------
-* ブロードキャストウィジェットの強化
-* デザインのグリッチの修正
-* 通信の最適化
-
-3113 (2017/11/15)
------------------
-* アクティビティのレンダリングの問題の修正など
-
-3110 (2017/11/15)
------------------
-* デザインの調整など
-
-3107 (2017/11/14)
------------------
-* デザインの調整
-
-3104 (2017/11/14)
------------------
-* デスクトップ版ユーザーページのデザインの改良
-* バグ修正
-
-3099 (2017/11/14)
------------------
-* デスクトップ版ユーザーページの強化
-* バグ修正
-
-3093 (2017/11/14)
------------------
-* やった
-
-3089 (2017/11/14)
------------------
-* なんか
-
-3069 (2017/11/14)
------------------
-* ドライブウィンドウもポップアウトできるように
-* デザインの調整
-
-3066 (2017/11/14)
------------------
-* メッセージウィジェット追加
-* アクセスログウィジェット追加
-
-3057 (2017/11/13)
------------------
-* グリッチ修正
-
-3055 (2017/11/13)
------------------
-* メッセージのウィンドウのポップアウト (#911)
-
-3050 (2017/11/13)
------------------
-* 通信の最適化
-  * これで例えばサーバー情報ウィジェットを5000兆個設置しても利用するコネクションは一つだけになりウィジェットを1つ設置したときと(ネットワーク的な)負荷は変わらなくなる
-* デザインの調整
-* ユーザビリティの向上
-
-3040 (2017/11/12)
------------------
-* バグ修正
-
-3038 (2017/11/12)
------------------
-* 投稿フォームウィジェットの追加
-* タイムライン上部にもウィジェットを配置できるように
-
-3035 (2017/11/12)
------------------
-* ウィジェットの強化
-
-3033 (2017/11/12)
------------------
-* デザインの調整
-
-3031 (2017/11/12)
------------------
-* ウィジェットの強化
-
-3028 (2017/11/12)
------------------
-* ウィジェットの表示をコンパクトにできるように
-
-3026 (2017/11/12)
------------------
-* バグ修正
-
-3024 (2017/11/12)
------------------
-* いい感じにするなど
-
-3020 (2017/11/12)
------------------
-* 通信の最適化
-
-3017 (2017/11/11)
------------------
-* 誤字修正など
-
-3012 (2017/11/11)
------------------
-* デザインの調整
-
-3010 (2017/11/11)
------------------
-* デザインの調整
-
-3008 (2017/11/11)
------------------
-* カレンダー(タイムマシン)ウィジェットの追加
-
-3006 (2017/11/11)
------------------
-* デザインの調整
-* など
-
-2996 (2017/11/10)
------------------
-* デザインの調整
-* など
-
-2991 (2017/11/09)
------------------
-* デザインの調整
-
-2988 (2017/11/09)
------------------
-* チャンネルウィジェットを追加
-
-2984 (2017/11/09)
------------------
-* スライドショーウィジェットを追加
-
-2974 (2017/11/08)
------------------
-* ホームのカスタマイズを実装するなど
-
-2971 (2017/11/08)
------------------
-* バグ修正
-* デザインの調整
-* i18n
-
-2944 (2017/11/07)
------------------
-* パフォーマンスの向上
-  * GirdFSになるなどした
-* 依存関係の更新
-
-2807 (2017/11/02)
------------------
-* いい感じに
-
-2805 (2017/11/02)
------------------
-* いい感じに
-
-2801 (2017/11/01)
------------------
-* チャンネルのWatch実装
-
-2799 (2017/11/01)
------------------
-* いい感じに
-
-2795 (2017/11/01)
------------------
-* いい感じに
-
-2793 (2017/11/01)
------------------
-* なんか
-
-2783 (2017/11/01)
------------------
-* なんか
-
-2777 (2017/11/01)
------------------
-* 細かいブラッシュアップ
-
-2775 (2017/11/01)
------------------
-* Fix: バグ修正
-
-2769 (2017/11/01)
------------------
-* New: チャンネルシステム
-
-2752 (2017/10/30)
------------------
-* New: 未読の通知がある場合アイコンを表示するように
-
-2747 (2017/10/25)
------------------
-* Fix: 非ログイン状態ですべてのページが致命的な問題を発生させる (#89)
-
-2742 (2017/10/25)
------------------
-* New: トラブルシューティングを実装するなど
-
-2735 (2017/10/22)
------------------
-* New: モバイル版からでもクライアントバージョンを確認できるように
-
-2732 (2017/10/22)
------------------
-* 依存関係の更新など
-
-2584 (2017/09/08)
------------------
-* New: ユーザーページによく使うドメインを表示 (#771)
-* New: よくリプライするユーザーをユーザーページに表示 (#770)
-
-2566 (2017/09/07)
------------------
-* New: 投稿することの多いキーワードをユーザーページに表示する (#768)
-* l10n
-* デザインの修正
-
-2544 (2017/09/06)
------------------
-* 投稿のカテゴリに関する実験的な実装
-* l10n
-* ユーザビリティの向上
-
-2520 (2017/08/30)
------------------
-* デザインの調整
-
-2518 (2017/08/30)
------------------
-* Fix: モバイル版のタイムラインからリアクションやメニューを開けない
-* デザインの調整
-
-2515 (2017/08/30)
------------------
-* New: 投稿のピン留め (#746)
-* New: モバイル版のユーザーページに知り合いのフォロワーを表示するように
-* New: ホームストリームにメッセージを流すことでlast_used_atを更新できるようにする (#745)
-* その他細かな修正
-
-2508 (2017/08/30)
------------------
-* New: モバイル版のユーザーページのアクティビティチャートを変更
-* New: モバイル版のユーザーページに最終ログイン日時を表示するように
-* デザインの調整
-
-2503 (2017/08/30)
------------------
-* デザインの調整
-
-2502 (2017/08/30)
------------------
-* デザインの修正・調整
-
-2501 (2017/08/30)
------------------
-* New: モバイルのユーザーページを刷新
-
-2498 (2017/08/29)
------------------
-* Fix: repostのborder-radiusが効いていない (#743)
-* テーマカラーを赤に戻してみた
-* ユーザビリティの向上
-* デザインの調整
-
-2493-2 (2017/08/29)
--------------------
-* デザインの修正
-
-2493 (2017/08/29)
------------------
-* デザインの変更など
-
-2491 (2017/08/29)
------------------
-* デザインの修正と調整
-
-2489 (2017/08/29)
------------------
-* ユーザビリティの向上
-* デザインの調整
-
-2487 (2017/08/29)
------------------
-* New: パスワードを変更する際に新しいパスワードを二度入力させる (#739)
-* New: ドナーを表示する (#738)
-* Fix: 投稿のリンクが機能していない問題を修正
-* Fix: アカウント作成フォームのユーザーページURLプレビューが正しく機能していなかった問題を修正
-* l10n
-* デザインの調整
-
-2470 (2017/08/29)
------------------
-* New: トークンを再生成できるように (#497)
-* New: パスワードを変更する機能 (#364)
-
-2461 (2017/08/28)
------------------
-* Fix: モバイル版からアバターとバナーの設定を行えなかった問題を修正
-* デザインの修正
-
-2458 (2017/08/28)
------------------
-* New: モバイル版からプロフィールを設定できるように
-* New: モバイル版からサインアウトを行えるように
-* New: 投稿ページに次の投稿/前の投稿リンクを作成 (#734)
-* New: タイムラインの投稿をダブルクリックすることで詳細な情報が見れるように
-* Fix: モバイル版でおすすめユーザーをフォローしてもタイムラインが更新されない (#736)
-* Fix: モバイル版で設定にアクセスできない
-* デザインの調整
-* 依存関係の更新
-
-2380
-----
-アプリケーションが作れない問題を修正
-
-2367
-----
-Statsのユーザー数グラフに「アカウントが作成された**回数**」(その日時点での「アカウント数」**ではなく**)グラフも併記するようにした
-
-2364
-----
-デザインの微調整
-
-2361
-----
-Statsを実装するなど
-
-2357
-----
-Statusを実装するなど
diff --git a/README.md b/README.md
index cb8821b1e5..05a90ad23b 100644
--- a/README.md
+++ b/README.md
@@ -32,10 +32,6 @@ Contribution
 ----------------------------------------------------------------
 Please see [Contribution guide](./CONTRIBUTING.md).
 
-Release Notes
-----------------------------------------------------------------
-Please see [ChangeLog](./CHANGELOG.md).
-
 Sponsors & Backers
 ----------------------------------------------------------------
 Misskey has no 100+ GitHub stars currently. However, a donation is always welcome!

From 98ce8dd9522ed7e23a82b6cf8e3e47cd84f6b834 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 22:30:52 +0900
Subject: [PATCH 31/43] :v:

---
 README.md | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 05a90ad23b..7034007556 100644
--- a/README.md
+++ b/README.md
@@ -39,11 +39,11 @@ If you want to donate to Misskey, please get in touch with [@syuilo][syuilo-link
 
 **Note:** When you donate to Misskey, your name will be listed in [donors](./DONORS.md).
 
-Collaborators
+Notable contributors
 ----------------------------------------------------------------
-| ![syuilo][syuilo-icon] | ![Morisawa Aya][ayamorisawa-icon] | ![otofune][otofune-icon]        |
-|------------------------|-----------------------------------|---------------------------------|
-| [syuilo][syuilo-link]  | [Aya Morisawa][ayamorisawa-link]  | [otofune][otofune-link] |
+| ![syuilo][syuilo-icon] | ![Morisawa Aya][ayamorisawa-icon] | ![otofune][otofune-icon] | ![akihikodaki][akihikodaki-icon] |
+|:-:|:-:|:-:|:-:|
+| [syuilo][syuilo-link]<br>Owner | [Aya Morisawa][ayamorisawa-link]<br>Collaborator | [otofune][otofune-link]<br>Collaborator | [akihikodaki][akihikodaki-link] |
 
 [List of all contributors](https://github.com/syuilo/misskey/graphs/contributors)
 
@@ -65,10 +65,12 @@ license is applied.) See Git log to identify them.
 [himawari-badge]:     https://img.shields.io/badge/%E5%8F%A4%E8%B0%B7-%E5%90%91%E6%97%A5%E8%91%B5-1684c5.svg?style=flat-square
 [sakurako-badge]:     https://img.shields.io/badge/%E5%A4%A7%E5%AE%A4-%E6%AB%BB%E5%AD%90-efb02a.svg?style=flat-square
 
-<!-- Collaborators Info -->
+<!-- Contributors Info -->
 [syuilo-link]:      https://syuilo.com
 [syuilo-icon]:      https://avatars2.githubusercontent.com/u/4439005?v=3&s=70
 [ayamorisawa-link]: https://github.com/ayamorisawa
 [ayamorisawa-icon]: https://avatars0.githubusercontent.com/u/10798641?v=3&s=70
 [otofune-link]:     https://github.com/otofune
 [otofune-icon]:     https://avatars0.githubusercontent.com/u/15062473?v=3&s=70
+[akihikodaki-link]: https://github.com/akihikodaki
+[akihikodaki-icon]: https://avatars2.githubusercontent.com/u/17036990?s=70&v=4

From c70a1ab11300e88301519ed95506c018ab1a34db Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 22:37:09 +0900
Subject: [PATCH 32/43] :art:

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 7034007556..df6056993f 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-![Misskey](./assets/title.png)
+<img src="https://github.com/syuilo/misskey/blob/b3f42e62af698a67c2250533c437569559f1fdf9/src/himasaku/resources/himasaku.png?raw=true" align="right" width="320px"/>
+
+Misskey
 ================================================================
 
 [![][travis-badge]][travis-link]
@@ -10,8 +12,6 @@
 [Misskey](https://misskey.xyz) is a completely open source,
 ultimately sophisticated new type of mini-blog based SNS.
 
-![ss](./assets/ss.jpg)
-
 Key features
 ----------------------------------------------------------------
 * Automatically updated timeline

From 7404a7ac18512602b7af40fc2bd7da8bb16ec424 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 22:44:30 +0900
Subject: [PATCH 33/43] :v:

---
 README.md | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index df6056993f..69a9221c8d 100644
--- a/README.md
+++ b/README.md
@@ -28,16 +28,11 @@ Setup and Installation
 If you want to run your own instance of Misskey,
 please see [Setup and installation guide](./docs/setup.en.md).
 
-Contribution
+Donation
 ----------------------------------------------------------------
-Please see [Contribution guide](./CONTRIBUTING.md).
+If you want to donate to Misskey, please see [this][./docs/donate.ja.md].
 
-Sponsors & Backers
-----------------------------------------------------------------
-Misskey has no 100+ GitHub stars currently. However, a donation is always welcome!
-If you want to donate to Misskey, please get in touch with [@syuilo][syuilo-link].
-
-**Note:** When you donate to Misskey, your name will be listed in [donors](./DONORS.md).
+[List of all donors](./DONORS.md)
 
 Notable contributors
 ----------------------------------------------------------------

From d792de9a7fe3067a5b49e405c02e7eb71a60bd92 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 22:56:28 +0900
Subject: [PATCH 34/43] Use AGPLv3

---
 LICENSE          | 674 +++++++++++++++++++++++++++++++++++++++++++++--
 LICENSE_AGPL-3.0 | 661 ----------------------------------------------
 README.md        |   6 +-
 3 files changed, 658 insertions(+), 683 deletions(-)
 delete mode 100644 LICENSE_AGPL-3.0

diff --git a/LICENSE b/LICENSE
index 0b6e30e45f..dba13ed2dd 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,661 @@
-The MIT License (MIT)
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
 
-Copyright (c) 2014-2018 syuilo
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+                            Preamble
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/LICENSE_AGPL-3.0 b/LICENSE_AGPL-3.0
deleted file mode 100644
index dba13ed2dd..0000000000
--- a/LICENSE_AGPL-3.0
+++ /dev/null
@@ -1,661 +0,0 @@
-                    GNU AFFERO GENERAL PUBLIC LICENSE
-                       Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
-  A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate.  Many developers of free software are heartened and
-encouraged by the resulting cooperation.  However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
-  The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community.  It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server.  Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
-  An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals.  This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU Affero General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Remote Network Interaction; Use with the GNU General Public License.
-
-  Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software.  This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time.  Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source.  For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code.  There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-<http://www.gnu.org/licenses/>.
diff --git a/README.md b/README.md
index 69a9221c8d..4302371096 100644
--- a/README.md
+++ b/README.md
@@ -44,11 +44,7 @@ Notable contributors
 
 Copyright
 ----------------------------------------------------------------
-Misskey is an open-source software licensed under [The MIT License](LICENSE).
-
-The portions of Misskey contributed by Akihiko Odaki <nekomanma@pixiv.co.jp> is
-licensed under GNU Affero General Public License (only version 3.0 of the
-license is applied.) See Git log to identify them.
+Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE).
 
 [agpl-3.0]:           https://www.gnu.org/licenses/agpl-3.0.en.html
 [agpl-3.0-badge]:     https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=flat-square

From 3abddd2449ab78b6bde44e382b0aea2aa1c356bf Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 23:01:42 +0900
Subject: [PATCH 35/43] :v:

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index 4302371096..800cad0f99 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,8 @@ Notable contributors
 
 Copyright
 ----------------------------------------------------------------
+> Copyright (c) 2014-2018 syuilo
+
 Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE).
 
 [agpl-3.0]:           https://www.gnu.org/licenses/agpl-3.0.en.html

From 7de4eaf0ff42cd9f95ec3bff9940308bc1ef687e Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 28 Mar 2018 23:04:06 +0900
Subject: [PATCH 36/43] :v:

---
 README.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 800cad0f99..6984f52f1c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,9 @@ Misskey
 [![][sakurako-badge]][himasaku]
 [![][agpl-3.0-badge]][AGPL-3.0]
 
-[Misskey](https://misskey.xyz) is a completely open source,
+> Lead Maintainer: [syuilo][syuilo-link]
+
+**[Misskey](https://misskey.xyz)** is a completely open source,
 ultimately sophisticated new type of mini-blog based SNS.
 
 Key features

From ba429c33d915d2ab47d0049e2bd0eb4e9496b833 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 11:08:53 +0900
Subject: [PATCH 37/43] oops

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 6984f52f1c..65d56a0f14 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ please see [Setup and installation guide](./docs/setup.en.md).
 
 Donation
 ----------------------------------------------------------------
-If you want to donate to Misskey, please see [this][./docs/donate.ja.md].
+If you want to donate to Misskey, please see [this](./docs/donate.ja.md).
 
 [List of all donors](./DONORS.md)
 

From acb0be9a662b5e95409d6bc7be8a14ac089562a8 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 11:13:40 +0900
Subject: [PATCH 38/43] Update README.md

---
 README.md | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 65d56a0f14..b743914f56 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Misskey
 **[Misskey](https://misskey.xyz)** is a completely open source,
 ultimately sophisticated new type of mini-blog based SNS.
 
-Key features
+:sparkles: Features
 ----------------------------------------------------------------
 * Automatically updated timeline
 * Private messages
@@ -25,18 +25,18 @@ Key features
 
 and more! You can touch with your own eyes at https://misskey.xyz/.
 
-Setup and Installation
+:package: Setup and Installation
 ----------------------------------------------------------------
 If you want to run your own instance of Misskey,
 please see [Setup and installation guide](./docs/setup.en.md).
 
-Donation
+:yen: Donation
 ----------------------------------------------------------------
 If you want to donate to Misskey, please see [this](./docs/donate.ja.md).
 
 [List of all donors](./DONORS.md)
 
-Notable contributors
+:mortar_board: Notable contributors
 ----------------------------------------------------------------
 | ![syuilo][syuilo-icon] | ![Morisawa Aya][ayamorisawa-icon] | ![otofune][otofune-icon] | ![akihikodaki][akihikodaki-icon] |
 |:-:|:-:|:-:|:-:|
@@ -44,7 +44,7 @@ Notable contributors
 
 [List of all contributors](https://github.com/syuilo/misskey/graphs/contributors)
 
-Copyright
+:four_leaf_clover: Copyright
 ----------------------------------------------------------------
 > Copyright (c) 2014-2018 syuilo
 

From c21235d07fdfec975f4c0efbc258511d0923465e Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 11:19:53 +0900
Subject: [PATCH 39/43] Update Dockerfile

---
 docker/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docker/Dockerfile b/docker/Dockerfile
index ef04fc9e26..7cee650de3 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -14,7 +14,7 @@ RUN pacman -S --noconfirm pacman
 RUN pacman-db-upgrade
 RUN pacman -S --noconfirm archlinux-keyring
 RUN pacman -Syyu --noconfirm
-RUN pacman -S --noconfirm git nodejs npm mongodb redis graphicsmagick
+RUN pacman -S --noconfirm git nodejs npm mongodb redis imagemagick
 
 COPY misskey.sh /root/misskey.sh
 RUN chmod u+x /root/misskey.sh

From f728fb4a1174ef981b8d9f4d789488d4040e1f29 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 11:34:20 +0900
Subject: [PATCH 40/43] :v:

---
 docs/config.md => .config/example.yml | 3 ---
 .gitignore                            | 3 ++-
 docs/setup.en.md                      | 6 +++---
 docs/setup.ja.md                      | 6 +++---
 4 files changed, 8 insertions(+), 10 deletions(-)
 rename docs/config.md => .config/example.yml (98%)

diff --git a/docs/config.md b/.config/example.yml
similarity index 98%
rename from docs/config.md
rename to .config/example.yml
index c4a54c0bee..0e167ccb77 100644
--- a/docs/config.md
+++ b/.config/example.yml
@@ -1,4 +1,3 @@
-``` yaml
 # サーバーのメンテナ情報
 maintainer:
   # メンテナの名前
@@ -56,5 +55,3 @@ twitter:
 
   # インテグレーション用アプリのコンシューマーシークレット
   consumer_secret:
-
-```
diff --git a/.gitignore b/.gitignore
index d0ae0b8085..be8689e2ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-/.config
+/.config/*
+!/.config/example.yml
 /.vscode
 /node_modules
 /build
diff --git a/docs/setup.en.md b/docs/setup.en.md
index 08cd16857d..a436d751c8 100644
--- a/docs/setup.en.md
+++ b/docs/setup.en.md
@@ -37,9 +37,9 @@ Please install and setup these softwares:
 
 *3.* Prepare configuration
 ----------------------------------------------------------------
-First, you need to create a `.config` directory in the directory that
-Misskey installed. And then you need to create a `default.yml` file in
-the directory. The template of configuration is available [here](./config.md).
+1. Copy `example.yml` of `.config` directory
+2. Rename it to `default.yml`
+3. Edit it
 
 *4.* Install and build Misskey
 ----------------------------------------------------------------
diff --git a/docs/setup.ja.md b/docs/setup.ja.md
index 9fa56acb22..6605461d9f 100644
--- a/docs/setup.ja.md
+++ b/docs/setup.ja.md
@@ -37,9 +37,9 @@ web-push generate-vapid-keys
 
 *3.* 設定ファイルを用意する
 ----------------------------------------------------------------
-Misskeyをインストールしたディレクトリに、`.config`というディレクトリを作成し、
-その中に`default.yml`という名前で設定ファイルを作ってください。
-設定ファイルの下書きは[ここ](./config.md)にありますので、コピペしてご利用ください。
+1. `.config`ディレクトリ内の`example.yml`をコピー
+2. `default.yml`にリネーム
+3. 編集する
 
 *4.* Misskeyのインストール(とビルド)
 ----------------------------------------------------------------

From 70fcf0976860db2d6c3b629db1a039e239679c02 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 11:44:24 +0900
Subject: [PATCH 41/43] Update README.md

---
 README.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index b743914f56..ef12958c2f 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,9 @@ If you want to donate to Misskey, please see [this](./docs/donate.ja.md).
 
 :mortar_board: Notable contributors
 ----------------------------------------------------------------
-| ![syuilo][syuilo-icon] | ![Morisawa Aya][ayamorisawa-icon] | ![otofune][otofune-icon] | ![akihikodaki][akihikodaki-icon] |
-|:-:|:-:|:-:|:-:|
-| [syuilo][syuilo-link]<br>Owner | [Aya Morisawa][ayamorisawa-link]<br>Collaborator | [otofune][otofune-link]<br>Collaborator | [akihikodaki][akihikodaki-link] |
+| ![syuilo][syuilo-icon] | ![Morisawa Aya][ayamorisawa-icon] | ![otofune][otofune-icon] | ![akihikodaki][akihikodaki-icon] | ![rinsuki][rinsuki-icon] |
+|:-:|:-:|:-:|:-:|:-:|
+| [syuilo][syuilo-link]<br>Owner | [Aya Morisawa][ayamorisawa-link]<br>Collaborator | [otofune][otofune-link]<br>Collaborator | [akihikodaki][akihikodaki-link] | [rinsuki][rinsuki-link] |
 
 [List of all contributors](https://github.com/syuilo/misskey/graphs/contributors)
 
@@ -69,3 +69,5 @@ Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE).
 [otofune-icon]:     https://avatars0.githubusercontent.com/u/15062473?v=3&s=70
 [akihikodaki-link]: https://github.com/akihikodaki
 [akihikodaki-icon]: https://avatars2.githubusercontent.com/u/17036990?s=70&v=4
+[rinsuki-link]:     https://github.com/rinsuki
+[rinsuki-icon]:     https://avatars0.githubusercontent.com/u/6533808?s=70&v=4

From bc6430c6d2c165f668f51bb281faeb86c0cb19c8 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 13:35:42 +0900
Subject: [PATCH 42/43] Remove unused const

---
 gulpfile.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gulpfile.ts b/gulpfile.ts
index 9c61e3a1cb..c72dedda2a 100644
--- a/gulpfile.ts
+++ b/gulpfile.ts
@@ -125,7 +125,6 @@ gulp.task('build:client:script', () =>
 		.pipe(replace('VERSION', JSON.stringify(version)))
 		.pipe(replace('API', JSON.stringify(config.api_url)))
 		.pipe(replace('ENV', JSON.stringify(env)))
-		.pipe(replace('HOST', JSON.stringify(config.host)))
 		.pipe(isProduction ? uglify({
 			toplevel: true
 		} as any) : gutil.noop())

From 1ffc345cdc8f0470a8e9e4d03bea3ae7af54ea48 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Thu, 29 Mar 2018 14:39:52 +0900
Subject: [PATCH 43/43] oops

---
 src/config.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/config.ts b/src/config.ts
index 0d8df39f44..6d3e7740b1 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -80,7 +80,7 @@ type Source = {
 	};
 	line_bot?: {
 		channel_secret: string;
-		channel_accessToken: string;
+		channel_access_token: string;
 	};
 	analysis?: {
 		mecab_command?: string;