From 5458b107743fcb6fa52b9527f08f36342339753f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 24 Jul 2018 01:58:11 +0900
Subject: [PATCH 1/5] wip

---
 .config/example.yml            | 16 ++++++++
 package.json                   |  2 +
 src/config/types.ts            |  8 ++++
 src/services/drive/add-file.ts | 68 ++++++++++++++++++----------------
 4 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/.config/example.yml b/.config/example.yml
index 6c939a4f3..28a850182 100644
--- a/.config/example.yml
+++ b/.config/example.yml
@@ -53,6 +53,22 @@ remoteDriveCapacityMb: 8
 #  Users cannot see remote images when they turn off "Show media from a remote server" setting.
 preventCache: false
 
+drive:
+  storage: 'db'
+
+  # OR
+
+  # storage: 'object-storage'
+  # service: 'minio'
+  # bucket:
+  # prefix:
+  # config:
+  #   endPoint:
+  #   port:
+  #   secure:
+  #   accessKey:
+  #   secretKey:
+
 #
 # Below settings are optional
 #
diff --git a/package.json b/package.json
index 845a6166b..849ff7a62 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,7 @@
 		"@types/koa-views": "2.0.3",
 		"@types/koa__cors": "2.2.2",
 		"@types/kue": "0.11.9",
+		"@types/minio": "6.0.2",
 		"@types/mkdirp": "0.5.2",
 		"@types/mocha": "5.2.3",
 		"@types/mongodb": "3.1.2",
@@ -147,6 +148,7 @@
 		"kue": "0.11.6",
 		"loader-utils": "1.1.0",
 		"mecab-async": "0.1.2",
+		"minio": "6.0.0",
 		"mkdirp": "0.5.1",
 		"mocha": "5.2.0",
 		"moji": "0.5.1",
diff --git a/src/config/types.ts b/src/config/types.ts
index c26ff9db9..b2e28f730 100644
--- a/src/config/types.ts
+++ b/src/config/types.ts
@@ -49,6 +49,14 @@ export type Source = {
 	remoteDriveCapacityMb: number;
 	preventCacheRemoteFiles: boolean;
 
+	drive?: {
+		storage: string;
+		bucket: string;
+		prefix: string;
+		service?: string;
+		config?: any;
+	};
+
 	/**
 	 * ゴーストアカウントのID
 	 */
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index f7c8922b5..a1b968695 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -8,14 +8,14 @@ import * as _gm from 'gm';
 import * as debug from 'debug';
 import fileType = require('file-type');
 const prominence = require('prominence');
+import * as Minio from 'minio';
+import * as uuid from 'uuid';
 
 import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file';
 import DriveFolder from '../../models/drive-folder';
 import { pack } from '../../models/drive-file';
 import event, { publishDriveStream } from '../../stream';
 import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
-import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
-import genThumbnail from '../../drive/gen-thumbnail';
 import delFile from './delete-file';
 import config from '../../config';
 
@@ -25,28 +25,43 @@ const gm = _gm.subClass({
 
 const log = debug('misskey:drive:add-file');
 
-const writeChunks = (name: string, readable: stream.Readable, type: string, metadata: any) =>
-	getDriveFileBucket()
-		.then(bucket => new Promise((resolve, reject) => {
+async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
+	if (config.drive && config.drive.storage == 'object-storage') {
+		if (config.drive.service == 'minio') {
+
+			const minio = new Minio.Client(config.drive.config);
+			const id = uuid.v4();
+			const obj = `${config.drive.prefix}/${id}`;
+			await minio.putObject(config.drive.bucket, obj, readable);
+
+			Object.assign(metadata, {
+				obj: id,
+				url: `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }/${ obj }`
+			});
+
+			const file = await DriveFile.insert({
+				length: size,
+				uploadDate: new Date(),
+				md5: hash,
+				filename: name,
+				metadata: metadata,
+				contentType: type
+			});
+
+			return file;
+		}
+	} else {
+		// Get MongoDB GridFS bucket
+		const bucket = await getDriveFileBucket();
+
+		return new Promise<IDriveFile>((resolve, reject) => {
 			const writeStream = bucket.openUploadStream(name, { contentType: type, metadata });
 			writeStream.once('finish', resolve);
 			writeStream.on('error', reject);
 			readable.pipe(writeStream);
-		}));
-
-const writeThumbnailChunks = (name: string, readable: stream.Readable, originalId: mongodb.ObjectID) =>
-	getDriveFileThumbnailBucket()
-		.then(bucket => new Promise((resolve, reject) => {
-			const writeStream = bucket.openUploadStream(name, {
-				contentType: 'image/jpeg',
-				metadata: {
-					originalId
-				}
-			});
-			writeStream.once('finish', resolve);
-			writeStream.on('error', reject);
-			readable.pipe(writeStream);
-		}));
+		});
+	}
+}
 
 async function deleteOldFile(user: IRemoteUser) {
 	const oldFile = await DriveFile.findOne({
@@ -283,7 +298,7 @@ export default async function(
 			metadata: metadata,
 			contentType: mime
 		})
-		: await (writeChunks(detectedName, fs.createReadStream(path), mime, metadata) as Promise<IDriveFile>);
+		: await (save(fs.createReadStream(path), detectedName, mime, hash, size, metadata));
 
 	log(`drive file has been created ${driveFile._id}`);
 
@@ -293,16 +308,7 @@ export default async function(
 		publishDriveStream(user._id, 'file_created', packedFile);
 	});
 
-	if (!metaOnly) {
-		try {
-			const thumb = await genThumbnail(driveFile);
-			if (thumb) {
-				await writeThumbnailChunks(detectedName, thumb, driveFile._id);
-			}
-		} catch (e) {
-			// noop
-		}
-	}
+	// TODO: サムネイル生成
 
 	return driveFile;
 }

From adc3c16ef3bd53a4f1bb84ab7ca0fcc64384fe8f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 24 Jul 2018 05:04:43 +0900
Subject: [PATCH 2/5] wip

---
 cli/clean-cached-remote-files.js        |  4 ++--
 src/models/drive-file.ts                |  7 ++++---
 src/remote/activitypub/models/person.ts |  8 ++++----
 src/server/file/send-drive-file.ts      |  2 +-
 src/services/drive/add-file.ts          | 16 +++++++++++-----
 5 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/cli/clean-cached-remote-files.js b/cli/clean-cached-remote-files.js
index a9c38a4cd..5b388c73b 100644
--- a/cli/clean-cached-remote-files.js
+++ b/cli/clean-cached-remote-files.js
@@ -9,7 +9,7 @@ const q = {
 	'metadata._user.host': {
 		$ne: null
 	},
-	'metadata.isMetaOnly': false
+	'metadata.withoutChunks': false
 };
 
 async function main() {
@@ -57,7 +57,7 @@ async function main() {
 
 					DriveFile.update({ _id: file._id }, {
 						$set: {
-							'metadata.isMetaOnly': true
+							'metadata.withoutChunks': true
 						}
 					})
 				]).then(async () => {
diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts
index 3a0390f79..0b7212665 100644
--- a/src/models/drive-file.ts
+++ b/src/models/drive-file.ts
@@ -31,8 +31,9 @@ export type IMetadata = {
 	comment: string;
 	uri?: string;
 	url?: string;
+	src?: string;
 	deletedAt?: Date;
-	isMetaOnly?: boolean;
+	withoutChunks?: boolean;
 	isSensitive?: boolean;
 };
 
@@ -155,9 +156,9 @@ export const pack = (
 
 	_target = Object.assign(_target, _file.metadata);
 
+	_target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
 	_target.src = _file.metadata.url;
-	_target.url = _file.metadata.isMetaOnly ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
-	_target.isRemote = _file.metadata.isMetaOnly;
+	_target.isRemote = _file.metadata.withoutChunks;
 
 	if (_target.properties == null) _target.properties = {};
 
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index eee4aa1bf..4ff8d23be 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -152,8 +152,8 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs
 
 	const avatarId = avatar ? avatar._id : null;
 	const bannerId = banner ? banner._id : null;
-	const avatarUrl = avatar && avatar.metadata.isMetaOnly ? avatar.metadata.url : null;
-	const bannerUrl = banner && banner.metadata.isMetaOnly ? banner.metadata.url : null;
+	const avatarUrl = avatar && avatar.metadata.url ? avatar.metadata.url : null;
+	const bannerUrl = banner && banner.metadata.url ? banner.metadata.url : null;
 
 	await User.update({ _id: user._id }, {
 		$set: {
@@ -243,8 +243,8 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver)
 			sharedInbox: person.sharedInbox,
 			avatarId: avatar ? avatar._id : null,
 			bannerId: banner ? banner._id : null,
-			avatarUrl: avatar && avatar.metadata.isMetaOnly ? avatar.metadata.url : null,
-			bannerUrl: banner && banner.metadata.isMetaOnly ? banner.metadata.url : null,
+			avatarUrl: avatar && avatar.metadata.url ? avatar.metadata.url : null,
+			bannerUrl: banner && banner.metadata.url ? banner.metadata.url : null,
 			description: htmlToMFM(person.summary),
 			followersCount,
 			followingCount,
diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts
index e04400317..1a76b0e41 100644
--- a/src/server/file/send-drive-file.ts
+++ b/src/server/file/send-drive-file.ts
@@ -37,7 +37,7 @@ export default async function(ctx: Koa.Context) {
 		return;
 	}
 
-	if (file.metadata.isMetaOnly) {
+	if (file.metadata.withoutChunks) {
 		ctx.status = 204;
 		return;
 	}
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index a1b968695..4f379a25b 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -35,6 +35,8 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
 			await minio.putObject(config.drive.bucket, obj, readable);
 
 			Object.assign(metadata, {
+				storage: 'object-storage',
+				withoutChunks: true,
 				obj: id,
 				url: `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }/${ obj }`
 			});
@@ -97,7 +99,7 @@ export default async function(
 	comment: string = null,
 	folderId: mongodb.ObjectID = null,
 	force: boolean = false,
-	metaOnly: boolean = false,
+	isLink: boolean = false,
 	url: string = null,
 	uri: string = null,
 	sensitive = false
@@ -165,7 +167,7 @@ export default async function(
 	}
 
 	//#region Check drive usage
-	if (!metaOnly) {
+	if (!isLink) {
 		const usage = await DriveFile
 			.aggregate([{
 				$match: {
@@ -277,19 +279,23 @@ export default async function(
 		folderId: folder !== null ? folder._id : null,
 		comment: comment,
 		properties: properties,
-		isMetaOnly: metaOnly,
+		withoutChunks: isLink,
 		isSensitive: sensitive
 	} as IMetadata;
 
 	if (url !== null) {
-		metadata.url = url;
+		metadata.src = url;
+
+		if (isLink) {
+			metadata.url = url;
+		}
 	}
 
 	if (uri !== null) {
 		metadata.uri = uri;
 	}
 
-	const driveFile = metaOnly
+	const driveFile = isLink
 		? await DriveFile.insert({
 			length: 0,
 			uploadDate: new Date(),

From a048939cf1714f20ae00aea0d4f2595241bcbd13 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 24 Jul 2018 06:21:21 +0900
Subject: [PATCH 3/5] wip

---
 src/models/drive-file.ts          |  2 ++
 src/services/drive/add-file.ts    |  6 ++--
 src/services/drive/delete-file.ts | 52 ++++++++++++++++++-------------
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts
index 0b7212665..f197f86d4 100644
--- a/src/models/drive-file.ts
+++ b/src/models/drive-file.ts
@@ -34,6 +34,8 @@ export type IMetadata = {
 	src?: string;
 	deletedAt?: Date;
 	withoutChunks?: boolean;
+	storage?: string;
+	storageProps?: any;
 	isSensitive?: boolean;
 };
 
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index 4f379a25b..ab9353c9f 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -35,9 +35,11 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
 			await minio.putObject(config.drive.bucket, obj, readable);
 
 			Object.assign(metadata, {
-				storage: 'object-storage',
 				withoutChunks: true,
-				obj: id,
+				storage: 'object-storage',
+				storageProps: {
+					id: id
+				},
 				url: `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }/${ obj }`
 			});
 
diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts
index 4ac60439b..bf9c80f48 100644
--- a/src/services/drive/delete-file.ts
+++ b/src/services/drive/delete-file.ts
@@ -1,30 +1,40 @@
+import * as Minio from 'minio';
 import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file';
 import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail';
+import config from '../../config';
 
 export default async function(file: IDriveFile, isExpired = false) {
-	// チャンクをすべて削除
-	await DriveFileChunk.remove({
-		files_id: file._id
-	});
-
-	await DriveFile.update({ _id: file._id }, {
-		$set: {
-			'metadata.deletedAt': new Date(),
-			'metadata.isExpired': isExpired
+	if (file.metadata.withoutChunks) {
+		if (file.metadata.storage == 'object-storage') {
+			const minio = new Minio.Client(config.drive.config);
+			const obj = `${config.drive.prefix}/${file.metadata.storageProps.id}`;
+			await minio.removeObject(config.drive.bucket, obj);
 		}
-	});
-
-	//#region サムネイルもあれば削除
-	const thumbnail = await DriveFileThumbnail.findOne({
-		'metadata.originalId': file._id
-	});
-
-	if (thumbnail) {
-		await DriveFileThumbnailChunk.remove({
-			files_id: thumbnail._id
+	} else {
+		// チャンクをすべて削除
+		await DriveFileChunk.remove({
+			files_id: file._id
 		});
 
-		await DriveFileThumbnail.remove({ _id: thumbnail._id });
+		await DriveFile.update({ _id: file._id }, {
+			$set: {
+				'metadata.deletedAt': new Date(),
+				'metadata.isExpired': isExpired
+			}
+		});
+
+		//#region サムネイルもあれば削除
+		const thumbnail = await DriveFileThumbnail.findOne({
+			'metadata.originalId': file._id
+		});
+
+		if (thumbnail) {
+			await DriveFileThumbnailChunk.remove({
+				files_id: thumbnail._id
+			});
+
+			await DriveFileThumbnail.remove({ _id: thumbnail._id });
+		}
+		//#endregion
 	}
-	//#endregion
 }

From 5e9fb8bd848d97da2e00f4e7f7fbe5e77e82b9b8 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 24 Jul 2018 23:35:19 +0900
Subject: [PATCH 4/5] wip

---
 {migration => cli/migration}/2.0.0.js |  4 +--
 {migration => cli/migration}/2.4.0.js |  4 +--
 cli/migration/5.0.0.js                | 10 ++++++++
 migration/README.md                   | 11 --------
 migration/init-migration-file.sh      | 37 ---------------------------
 package.json                          |  2 +-
 6 files changed, 15 insertions(+), 53 deletions(-)
 rename {migration => cli/migration}/2.0.0.js (88%)
 rename {migration => cli/migration}/2.4.0.js (91%)
 create mode 100644 cli/migration/5.0.0.js
 delete mode 100644 migration/README.md
 delete mode 100644 migration/init-migration-file.sh

diff --git a/migration/2.0.0.js b/cli/migration/2.0.0.js
similarity index 88%
rename from migration/2.0.0.js
rename to cli/migration/2.0.0.js
index eb8f5730c..f7298972e 100644
--- a/migration/2.0.0.js
+++ b/cli/migration/2.0.0.js
@@ -3,8 +3,8 @@
 const chalk = require('chalk');
 const sequential = require('promise-sequential');
 
-const { default: User } = require('../built/models/user');
-const { default: DriveFile } = require('../built/models/drive-file');
+const { default: User } = require('../../built/models/user');
+const { default: DriveFile } = require('../../built/models/drive-file');
 
 async function main() {
 	const promiseGens = [];
diff --git a/migration/2.4.0.js b/cli/migration/2.4.0.js
similarity index 91%
rename from migration/2.4.0.js
rename to cli/migration/2.4.0.js
index e9584a1df..aa37849aa 100644
--- a/migration/2.4.0.js
+++ b/cli/migration/2.4.0.js
@@ -3,8 +3,8 @@
 const chalk = require('chalk');
 const sequential = require('promise-sequential');
 
-const { default: User } = require('../built/models/user');
-const { default: DriveFile } = require('../built/models/drive-file');
+const { default: User } = require('../../built/models/user');
+const { default: DriveFile } = require('../../built/models/drive-file');
 
 async function main() {
 	const promiseGens = [];
diff --git a/cli/migration/5.0.0.js b/cli/migration/5.0.0.js
new file mode 100644
index 000000000..8c6f49ed8
--- /dev/null
+++ b/cli/migration/5.0.0.js
@@ -0,0 +1,10 @@
+const { default: DriveFile } = require('../../built/models/drive-file');
+
+DriveFile.update({}, {
+	$rename: {
+		'metadata.url': 'metadata.src',
+		'metadata.isMetaOnly': 'metadata.withoutChunks',
+	}
+}, {
+	multi: true
+});
diff --git a/migration/README.md b/migration/README.md
deleted file mode 100644
index d52e84b35..000000000
--- a/migration/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Misskeyの破壊的変更に対応するいくつかのスニペットがあります。
-MongoDBシェルで実行する必要のあるものとnodeで直接実行する必要のあるものがあります。
-ファイル名が `shell.` から始まるものは前者、 `node.` から始まるものは後者です。
-
-MongoDBシェルで実行する場合、`use`でデータベースを選択しておく必要があります。
-
-nodeで実行するいくつかのスニペットは、並列処理させる数を引数で設定できるものがあります。
-処理中にエラーで落ちる場合は、メモリが足りていない可能性があるので、少ない数に設定してみてください。
-※デフォルトは`5`です。
-
-ファイルを作成する際は `../init-migration-file.sh -t _type_ -n _name_` を実行すると _type_._unixtime_._name_.js が生成されます
diff --git a/migration/init-migration-file.sh b/migration/init-migration-file.sh
deleted file mode 100644
index c6a2b862e..000000000
--- a/migration/init-migration-file.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-
-usage() {
-		echo "$0 [-t type] [-n name]"
-		echo "  type: [node | shell]"
-		echo "  name: if no present, set untitled"
-		exit 0
-}
-
-while getopts :t:n:h OPT
-do
-	case $OPT in
-		t)	type=$OPTARG
-				;;
-		n)	name=$OPTARG
-				;;
-		h)	usage
-				;;
-		\?) usage
-				;;
-		:)	usage
-				;;
-	esac
-done
-
-if [ "$type" = "" ]
-then
-	echo "no type present!!!"
-	usage
-fi
-
-if [ "$name" = "" ]
-then
-	name="untitled"
-fi
-
-touch "$(realpath $(dirname $BASH_SOURCE))/migration/$type.$(date +%s).$name.js"
diff --git a/package.json b/package.json
index 849ff7a62..3ca36923f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
 	"name": "misskey",
 	"author": "syuilo <i@syuilo.com>",
-	"version": "4.27.0",
+	"version": "5.0.0",
 	"clientVersion": "1.0.7487",
 	"codename": "nighthike",
 	"main": "./built/index.js",

From 03ce87d710b9194a43370dd1736e38b2dde2aa55 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 24 Jul 2018 23:43:14 +0900
Subject: [PATCH 5/5] wip

---
 src/client/app/auth/views/form.vue                 |  2 +-
 .../app/common/scripts/compose-notification.ts     | 14 +++++++-------
 .../app/common/views/components/autocomplete.vue   |  2 +-
 src/client/app/common/views/components/avatar.vue  |  2 +-
 .../components/games/reversi/reversi.game.vue      |  4 ++--
 .../app/common/views/widgets/photo-stream.vue      |  2 +-
 src/client/app/common/views/widgets/slideshow.vue  |  2 +-
 .../app/desktop/views/components/drive.file.vue    |  2 +-
 .../desktop/views/components/followers-window.vue  |  2 +-
 .../desktop/views/components/following-window.vue  |  2 +-
 .../app/desktop/views/components/media-image.vue   |  2 +-
 .../app/desktop/views/components/media-video.vue   |  2 +-
 .../app/desktop/views/components/post-form.vue     |  2 +-
 .../desktop/views/components/settings.profile.vue  |  2 +-
 .../app/desktop/views/components/user-preview.vue  |  2 +-
 .../views/pages/user/user.followers-you-know.vue   |  2 +-
 .../app/desktop/views/pages/user/user.photos.vue   |  2 +-
 src/client/app/desktop/views/widgets/profile.vue   |  2 +-
 .../app/mobile/views/components/drive.file.vue     |  2 +-
 .../app/mobile/views/components/media-image.vue    |  2 +-
 .../app/mobile/views/components/media-video.vue    |  2 +-
 .../app/mobile/views/components/note-card.vue      |  2 +-
 .../app/mobile/views/components/post-form.vue      |  2 +-
 src/client/app/mobile/views/components/ui.nav.vue  |  2 +-
 .../app/mobile/views/components/user-card.vue      |  2 +-
 src/client/app/mobile/views/pages/followers.vue    |  2 +-
 src/client/app/mobile/views/pages/following.vue    |  2 +-
 src/client/app/mobile/views/pages/user.vue         |  2 +-
 .../views/pages/user/home.followers-you-know.vue   |  2 +-
 .../app/mobile/views/pages/user/home.photos.vue    |  2 +-
 src/client/app/mobile/views/widgets/profile.vue    |  4 ++--
 31 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/src/client/app/auth/views/form.vue b/src/client/app/auth/views/form.vue
index 152b90042..80086e386 100644
--- a/src/client/app/auth/views/form.vue
+++ b/src/client/app/auth/views/form.vue
@@ -2,7 +2,7 @@
 <div class="form">
 	<header>
 		<h1><i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?</h1>
-		<img :src="`${app.iconUrl}?thumbnail&size=64`"/>
+		<img :src="app.iconUrl"/>
 	</header>
 	<div class="app">
 		<section>
diff --git a/src/client/app/common/scripts/compose-notification.ts b/src/client/app/common/scripts/compose-notification.ts
index 47499e549..c93609bc5 100644
--- a/src/client/app/common/scripts/compose-notification.ts
+++ b/src/client/app/common/scripts/compose-notification.ts
@@ -17,21 +17,21 @@ export default function(type, data): Notification {
 			return {
 				title: 'ファイルがアップロードされました',
 				body: data.name,
-				icon: data.url + '?thumbnail&size=64'
+				icon: data.url
 			};
 
 		case 'unread_messaging_message':
 			return {
 				title: `${getUserName(data.user)}さんからメッセージ:`,
 				body: data.text, // TODO: getMessagingMessageSummary(data),
-				icon: data.user.avatarUrl + '?thumbnail&size=64'
+				icon: data.user.avatarUrl
 			};
 
 		case 'reversi_invited':
 			return {
 				title: '対局への招待があります',
 				body: `${getUserName(data.parent)}さんから`,
-				icon: data.parent.avatarUrl + '?thumbnail&size=64'
+				icon: data.parent.avatarUrl
 			};
 
 		case 'notification':
@@ -40,28 +40,28 @@ export default function(type, data): Notification {
 					return {
 						title: `${getUserName(data.user)}さんから:`,
 						body: getNoteSummary(data),
-						icon: data.user.avatarUrl + '?thumbnail&size=64'
+						icon: data.user.avatarUrl
 					};
 
 				case 'reply':
 					return {
 						title: `${getUserName(data.user)}さんから返信:`,
 						body: getNoteSummary(data),
-						icon: data.user.avatarUrl + '?thumbnail&size=64'
+						icon: data.user.avatarUrl
 					};
 
 				case 'quote':
 					return {
 						title: `${getUserName(data.user)}さんが引用:`,
 						body: getNoteSummary(data),
-						icon: data.user.avatarUrl + '?thumbnail&size=64'
+						icon: data.user.avatarUrl
 					};
 
 				case 'reaction':
 					return {
 						title: `${getUserName(data.user)}: ${getReactionEmoji(data.reaction)}:`,
 						body: getNoteSummary(data.note),
-						icon: data.user.avatarUrl + '?thumbnail&size=64'
+						icon: data.user.avatarUrl
 					};
 
 				default:
diff --git a/src/client/app/common/views/components/autocomplete.vue b/src/client/app/common/views/components/autocomplete.vue
index 4a130a04e..cd6066877 100644
--- a/src/client/app/common/views/components/autocomplete.vue
+++ b/src/client/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.avatarUrl}?thumbnail&size=32`" alt=""/>
+			<img class="avatar" :src="user.avatarUrl" alt=""/>
 			<span class="name">{{ user | userName }}</span>
 			<span class="username">@{{ user | acct }}</span>
 		</li>
diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue
index a65b62882..a924b62e6 100644
--- a/src/client/app/common/views/components/avatar.vue
+++ b/src/client/app/common/views/components/avatar.vue
@@ -31,7 +31,7 @@ export default Vue.extend({
 					: this.user.avatarColor && this.user.avatarColor.length == 3
 						? `rgb(${ this.user.avatarColor.join(',') })`
 						: null,
-				backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl }?thumbnail)`,
+				backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl })`,
 				borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
 			};
 		}
diff --git a/src/client/app/common/views/components/games/reversi/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue
index ed9e71849..303070ffd 100644
--- a/src/client/app/common/views/components/games/reversi/reversi.game.vue
+++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue
@@ -26,8 +26,8 @@
 						: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="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">
-					<img v-if="stone === true" :src="`${blackUser.avatarUrl}?thumbnail&size=128`" alt="">
-					<img v-if="stone === false" :src="`${whiteUser.avatarUrl}?thumbnail&size=128`" alt="">
+					<img v-if="stone === true" :src="blackUser.avatarUrl" alt="">
+					<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="">
 				</div>
 			</div>
 			<div class="labels-y" v-if="this.$store.state.settings.reversiBoardLabels">
diff --git a/src/client/app/common/views/widgets/photo-stream.vue b/src/client/app/common/views/widgets/photo-stream.vue
index ae5924bb1..3e24c58e8 100644
--- a/src/client/app/common/views/widgets/photo-stream.vue
+++ b/src/client/app/common/views/widgets/photo-stream.vue
@@ -5,7 +5,7 @@
 
 		<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
 		<div :class="$style.stream" v-if="!fetching && images.length > 0">
-			<div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div>
+			<div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url})`"></div>
 		</div>
 		<p :class="$style.empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p>
 	</mk-widget-container>
diff --git a/src/client/app/common/views/widgets/slideshow.vue b/src/client/app/common/views/widgets/slideshow.vue
index e1c28f511..2eede0378 100644
--- a/src/client/app/common/views/widgets/slideshow.vue
+++ b/src/client/app/common/views/widgets/slideshow.vue
@@ -72,7 +72,7 @@ export default define({
 			if (this.images.length == 0) return;
 
 			const index = Math.floor(Math.random() * this.images.length);
-			const img = `url(${ this.images[index].url }?thumbnail&size=1024)`;
+			const img = `url(${ this.images[index].url })`;
 
 			(this.$refs.slideB as any).style.backgroundImage = img;
 
diff --git a/src/client/app/desktop/views/components/drive.file.vue b/src/client/app/desktop/views/components/drive.file.vue
index 11700d496..e1db36f5c 100644
--- a/src/client/app/desktop/views/components/drive.file.vue
+++ b/src/client/app/desktop/views/components/drive.file.vue
@@ -16,7 +16,7 @@
 		<p>%i18n:@banner%</p>
 	</div>
 	<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
-		<img :src="`${file.url}?thumbnail&size=128`" alt="" @load="onThumbnailLoaded"/>
+		<img :src="file.url" alt="" @load="onThumbnailLoaded"/>
 	</div>
 	<p class="name">
 		<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
diff --git a/src/client/app/desktop/views/components/followers-window.vue b/src/client/app/desktop/views/components/followers-window.vue
index 7ed31315f..fdab7bc1c 100644
--- a/src/client/app/desktop/views/components/followers-window.vue
+++ b/src/client/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.avatarUrl}?thumbnail&size=64`" alt=""/>{{ '%i18n:@followers%'.replace('{}', name) }}
+		<img :src="user.avatarUrl" alt=""/>{{ '%i18n:@followers%'.replace('{}', name) }}
 	</span>
 	<mk-followers :user="user"/>
 </mk-window>
diff --git a/src/client/app/desktop/views/components/following-window.vue b/src/client/app/desktop/views/components/following-window.vue
index b97f21e2a..7cca833a8 100644
--- a/src/client/app/desktop/views/components/following-window.vue
+++ b/src/client/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.avatarUrl}?thumbnail&size=64`" alt=""/>{{ '%i18n:@following%'.replace('{}', name) }}
+		<img :src="user.avatarUrl" alt=""/>{{ '%i18n:@following%'.replace('{}', name) }}
 	</span>
 	<mk-following :user="user"/>
 </mk-window>
diff --git a/src/client/app/desktop/views/components/media-image.vue b/src/client/app/desktop/views/components/media-image.vue
index 42a31c4c2..74bb03f4e 100644
--- a/src/client/app/desktop/views/components/media-image.vue
+++ b/src/client/app/desktop/views/components/media-image.vue
@@ -37,7 +37,7 @@ export default Vue.extend({
 		style(): any {
 			return {
 				'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
-				'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)`
+				'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url})`
 			};
 		}
 	},
diff --git a/src/client/app/desktop/views/components/media-video.vue b/src/client/app/desktop/views/components/media-video.vue
index 9f508cf1b..6c60f2da9 100644
--- a/src/client/app/desktop/views/components/media-video.vue
+++ b/src/client/app/desktop/views/components/media-video.vue
@@ -45,7 +45,7 @@ export default Vue.extend({
 	computed: {
 		imageStyle(): any {
 			return {
-				'background-image': `url(${this.video.url}?thumbnail&size=512)`
+				'background-image': `url(${this.video.url})`
 			};
 		}
 	},
diff --git a/src/client/app/desktop/views/components/post-form.vue b/src/client/app/desktop/views/components/post-form.vue
index 5ae44edda..775c08cc8 100644
--- a/src/client/app/desktop/views/components/post-form.vue
+++ b/src/client/app/desktop/views/components/post-form.vue
@@ -23,7 +23,7 @@
 		<div class="medias" :class="{ with: poll }" v-show="files.length != 0">
 			<x-draggable :list="files" :options="{ animation: 150 }">
 				<div v-for="file in files" :key="file.id">
-					<div class="img" :style="{ backgroundImage: `url(${file.url}?thumbnail&size=64)` }" :title="file.name"></div>
+					<div class="img" :style="{ backgroundImage: `url(${file.url})` }" :title="file.name"></div>
 					<img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/>
 				</div>
 			</x-draggable>
diff --git a/src/client/app/desktop/views/components/settings.profile.vue b/src/client/app/desktop/views/components/settings.profile.vue
index 0b3a25f38..ca29a120c 100644
--- a/src/client/app/desktop/views/components/settings.profile.vue
+++ b/src/client/app/desktop/views/components/settings.profile.vue
@@ -2,7 +2,7 @@
 <div class="profile">
 	<label class="avatar ui from group">
 		<p>%i18n:@avatar%</p>
-		<img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
+		<img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/>
 		<button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button>
 	</label>
 	<label class="ui from group">
diff --git a/src/client/app/desktop/views/components/user-preview.vue b/src/client/app/desktop/views/components/user-preview.vue
index 933e701e5..2a6815087 100644
--- a/src/client/app/desktop/views/components/user-preview.vue
+++ b/src/client/app/desktop/views/components/user-preview.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-user-preview">
 	<template v-if="u != null">
-		<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl}?thumbnail&size=512)` : ''"></div>
+		<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl})` : ''"></div>
 		<mk-avatar class="avatar" :user="u" :disable-preview="true"/>
 		<div class="title">
 			<router-link class="name" :to="u | userPage">{{ u | userName }}</router-link>
diff --git a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue b/src/client/app/desktop/views/pages/user/user.followers-you-know.vue
index 4c1b91e7a..e4a771910 100644
--- a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue
+++ b/src/client/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:@loading%<mk-ellipsis/></p>
 	<div v-if="!fetching && users.length > 0">
 	<router-link v-for="user in users" :to="user | userPage" :key="user.id">
-		<img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName" v-user-preview="user.id"/>
+		<img :src="user.avatarUrl" :alt="user | userName" v-user-preview="user.id"/>
 	</router-link>
 	</div>
 	<p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p>
diff --git a/src/client/app/desktop/views/pages/user/user.photos.vue b/src/client/app/desktop/views/pages/user/user.photos.vue
index 01c4c7b31..ce7791a96 100644
--- a/src/client/app/desktop/views/pages/user/user.photos.vue
+++ b/src/client/app/desktop/views/pages/user/user.photos.vue
@@ -4,7 +4,7 @@
 	<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
 	<div class="stream" v-if="!fetching && images.length > 0">
 		<div v-for="image in images" class="img"
-			:style="`background-image: url(${image.url}?thumbnail&size=256)`"
+			:style="`background-image: url(${image.url})`"
 		></div>
 	</div>
 	<p class="empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p>
diff --git a/src/client/app/desktop/views/widgets/profile.vue b/src/client/app/desktop/views/widgets/profile.vue
index 7b0fea372..9702aaa90 100644
--- a/src/client/app/desktop/views/widgets/profile.vue
+++ b/src/client/app/desktop/views/widgets/profile.vue
@@ -4,7 +4,7 @@
 	:data-melt="props.design == 2"
 >
 	<div class="banner"
-		:style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''"
+		:style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl})` : ''"
 		title="%i18n:@update-banner%"
 		@click="os.apis.updateBanner"
 	></div>
diff --git a/src/client/app/mobile/views/components/drive.file.vue b/src/client/app/mobile/views/components/drive.file.vue
index 94c8ae353..776e11ecf 100644
--- a/src/client/app/mobile/views/components/drive.file.vue
+++ b/src/client/app/mobile/views/components/drive.file.vue
@@ -43,7 +43,7 @@ export default Vue.extend({
 		thumbnail(): any {
 			return {
 				'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
-				'background-image': `url(${this.file.url}?thumbnail&size=128)`
+				'background-image': `url(${this.file.url})`
 			};
 		}
 	},
diff --git a/src/client/app/mobile/views/components/media-image.vue b/src/client/app/mobile/views/components/media-image.vue
index 1042404c9..d9d68fa7b 100644
--- a/src/client/app/mobile/views/components/media-image.vue
+++ b/src/client/app/mobile/views/components/media-image.vue
@@ -27,7 +27,7 @@ export default Vue.extend({
 	},
 	computed: {
 		style(): any {
-			let url = `url(${this.image.url}?thumbnail)`;
+			let url = `url(${this.image.url})`;
 
 			if (this.$store.state.device.loadRemoteMedia || this.$store.state.device.lightmode) {
 				url = null;
diff --git a/src/client/app/mobile/views/components/media-video.vue b/src/client/app/mobile/views/components/media-video.vue
index 26c9dcc2a..aea7f4146 100644
--- a/src/client/app/mobile/views/components/media-video.vue
+++ b/src/client/app/mobile/views/components/media-video.vue
@@ -30,7 +30,7 @@ export default Vue.extend({
 	computed: {
 		imageStyle(): any {
 			return {
-				'background-image': `url(${this.video.url}?thumbnail&size=512)`
+				'background-image': `url(${this.video.url})`
 			};
 		}
 	},})
diff --git a/src/client/app/mobile/views/components/note-card.vue b/src/client/app/mobile/views/components/note-card.vue
index 6d94c852b..e8427798c 100644
--- a/src/client/app/mobile/views/components/note-card.vue
+++ b/src/client/app/mobile/views/components/note-card.vue
@@ -2,7 +2,7 @@
 <div class="mk-note-card">
 	<a :href="note | notePage">
 		<header>
-			<img :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/><h3>{{ note.user | userName }}</h3>
+			<img :src="note.user.avatarUrl" alt="avatar"/><h3>{{ note.user | userName }}</h3>
 		</header>
 		<div>
 			{{ text }}
diff --git a/src/client/app/mobile/views/components/post-form.vue b/src/client/app/mobile/views/components/post-form.vue
index c558178cb..1d44258e5 100644
--- a/src/client/app/mobile/views/components/post-form.vue
+++ b/src/client/app/mobile/views/components/post-form.vue
@@ -21,7 +21,7 @@
 			<div class="attaches" v-show="files.length != 0">
 				<x-draggable class="files" :list="files" :options="{ animation: 150 }">
 					<div class="file" v-for="file in files" :key="file.id">
-						<div class="img" :style="`background-image: url(${file.url}?thumbnail&size=128)`" @click="detachMedia(file)"></div>
+						<div class="img" :style="`background-image: url(${file.url})`" @click="detachMedia(file)"></div>
 					</div>
 				</x-draggable>
 			</div>
diff --git a/src/client/app/mobile/views/components/ui.nav.vue b/src/client/app/mobile/views/components/ui.nav.vue
index bb7a2f558..5257dafd0 100644
--- a/src/client/app/mobile/views/components/ui.nav.vue
+++ b/src/client/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="$store.getters.isSignedIn" :to="`/@${$store.state.i.username}`">
-				<img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=128`" alt="avatar"/>
+				<img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/>
 				<p class="name">{{ $store.state.i | userName }}</p>
 			</router-link>
 			<div class="links">
diff --git a/src/client/app/mobile/views/components/user-card.vue b/src/client/app/mobile/views/components/user-card.vue
index 808ee7240..7b8f2251b 100644
--- a/src/client/app/mobile/views/components/user-card.vue
+++ b/src/client/app/mobile/views/components/user-card.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="mk-user-card">
-	<header :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=1024)` : ''">
+	<header :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''">
 		<mk-avatar class="avatar" :user="user"/>
 	</header>
 	<a class="name" :href="user | userPage" target="_blank">{{ user | userName }}</a>
diff --git a/src/client/app/mobile/views/pages/followers.vue b/src/client/app/mobile/views/pages/followers.vue
index f53fadb58..7dc72a7c3 100644
--- a/src/client/app/mobile/views/pages/followers.vue
+++ b/src/client/app/mobile/views/pages/followers.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<template slot="header" v-if="!fetching">
-		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
+		<img :src="user.avatarUrl" alt="">
 		{{ '%i18n:@followers-of%'.replace('{}', name) }}
 	</template>
 	<mk-users-list
diff --git a/src/client/app/mobile/views/pages/following.vue b/src/client/app/mobile/views/pages/following.vue
index b28d7dd7b..6895a76d5 100644
--- a/src/client/app/mobile/views/pages/following.vue
+++ b/src/client/app/mobile/views/pages/following.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<template slot="header" v-if="!fetching">
-		<img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">
+		<img :src="user.avatarUrl" alt="">
 		{{ '%i18n:@following-of%'.replace('{}', name) }}
 	</template>
 	<mk-users-list
diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue
index 0b51c8b4c..2bc89b81b 100644
--- a/src/client/app/mobile/views/pages/user.vue
+++ b/src/client/app/mobile/views/pages/user.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<template slot="header" v-if="!fetching"><img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">{{ user | userName }}</template>
+	<template slot="header" v-if="!fetching"><img :src="user.avatarUrl" alt="">{{ user | userName }}</template>
 	<main v-if="!fetching" :data-darkmode="$store.state.device.darkmode">
 		<div class="is-suspended" v-if="user.isSuspended"><p>%fa:exclamation-triangle% %i18n:@is-suspended%</p></div>
 		<div class="is-remote" v-if="user.host != null"><p>%fa:exclamation-triangle% %i18n:@is-remote%<a :href="user.url || user.uri" target="_blank">%i18n:@view-remote%</a></p></div>
diff --git a/src/client/app/mobile/views/pages/user/home.followers-you-know.vue b/src/client/app/mobile/views/pages/user/home.followers-you-know.vue
index 6f809d889..d5e3bef96 100644
--- a/src/client/app/mobile/views/pages/user/home.followers-you-know.vue
+++ b/src/client/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:@loading%<mk-ellipsis/></p>
 	<div v-if="!fetching && users.length > 0">
 		<a v-for="user in users" :key="user.id" :href="user | userPage">
-			<img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName"/>
+			<img :src="user.avatarUrl" :alt="user | userName"/>
 		</a>
 	</div>
 	<p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p>
diff --git a/src/client/app/mobile/views/pages/user/home.photos.vue b/src/client/app/mobile/views/pages/user/home.photos.vue
index bfd2aa833..73ff1d517 100644
--- a/src/client/app/mobile/views/pages/user/home.photos.vue
+++ b/src/client/app/mobile/views/pages/user/home.photos.vue
@@ -4,7 +4,7 @@
 	<div class="stream" v-if="!fetching && images.length > 0">
 		<a v-for="image in images"
 			class="img"
-			:style="`background-image: url(${image.media.url}?thumbnail&size=256)`"
+			:style="`background-image: url(${image.media.url})`"
 			:href="image.note | notePage"
 		></a>
 	</div>
diff --git a/src/client/app/mobile/views/widgets/profile.vue b/src/client/app/mobile/views/widgets/profile.vue
index a94f7e94b..6ce3468c4 100644
--- a/src/client/app/mobile/views/widgets/profile.vue
+++ b/src/client/app/mobile/views/widgets/profile.vue
@@ -2,10 +2,10 @@
 <div class="mkw-profile">
 	<mk-widget-container>
 		<div :class="$style.banner"
-			:style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''"
+			:style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl})` : ''"
 		></div>
 		<img :class="$style.avatar"
-			:src="`${$store.state.i.avatarUrl}?thumbnail&size=96`"
+			:src="$store.state.i.avatarUrl"
 			alt="avatar"
 		/>
 		<router-link :class="$style.name" :to="$store.state.i | userPage">{{ $store.state.i | userName }}</router-link>