From 3cd04c4b81190e4cfe6dc1def8335be02f8b4b37 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Sun, 23 May 2021 13:07:11 +0900
Subject: [PATCH 01/28] Fix agent type (#7532)

---
 yarn.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 3d84305649..9e32e6e913 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1536,9 +1536,9 @@ acorn@^8.2.1:
   integrity sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==
 
 agent-base@6:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a"
-  integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+  integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
   dependencies:
     debug "4"
 

From 7063a6925fb4cfa47747193e88c059514730ff44 Mon Sep 17 00:00:00 2001
From: okayurisotto <47853651+okayurisotto@users.noreply.github.com>
Date: Sun, 23 May 2021 18:55:21 +0900
Subject: [PATCH 02/28] =?UTF-8?q?fix:=20Safari=E3=81=A7=E3=82=82=E3=83=A2?=
 =?UTF-8?q?=E3=83=BC=E3=83=80=E3=83=AB=E3=81=AE=E3=81=BC=E3=81=8B=E3=81=97?=
 =?UTF-8?q?=E5=8A=B9=E6=9E=9C=E3=81=8C=E5=8A=B9=E3=81=8F=E3=82=88=E3=81=86?=
 =?UTF-8?q?=E3=81=AB=E3=81=97=E3=81=9F=20(#7530)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

https://github.com/misskey-dev/misskey/issues/7529
---
 src/client/style.scss | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/client/style.scss b/src/client/style.scss
index 39bf6ef2d5..dc419bd872 100644
--- a/src/client/style.scss
+++ b/src/client/style.scss
@@ -146,6 +146,7 @@ hr {
 	width: 100%;
 	height: 100%;
 	background: var(--modalBg);
+	-webkit-backdrop-filter: var(--modalBgFilter);
 	backdrop-filter: var(--modalBgFilter);
 }
 

From 47aaf044813662931fbaddd965272267fd94ed6a Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Sun, 23 May 2021 18:57:12 +0900
Subject: [PATCH 03/28] Fix search-by-tag (#7531)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix search-by-tag

* Revert "Fix search-by-tag"

This reverts commit c971d1d5d82f2d8b58fdec76e42f4404339ab83a.

* Fix typo

* Remove unused var

* インジェクションは[]を返すように
---
 .../api/endpoints/notes/search-by-tag.ts      | 35 ++++++++++---------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
index 61f62dd5a6..463c5fff5a 100644
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/src/server/api/endpoints/notes/search-by-tag.ts
@@ -104,22 +104,25 @@ export default define(meta, async (ps, me) => {
 	generateVisibilityQuery(query, me);
 	if (me) generateMutedUserQuery(query, me);
 
-	if (ps.tag) {
-		if (!safeForSql(ps.tag)) return;
-		query.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
-	} else {
-		let i = 0;
-		query.andWhere(new Brackets(qb => {
-			for (const tags of ps.query!) {
-				qb.orWhere(new Brackets(qb => {
-					for (const tag of tags) {
-						if (!safeForSql(tag)) return;
-						qb.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
-						i++;
-					}
-				}));
-			}
-		}));
+	try {
+		if (ps.tag) {
+			if (!safeForSql(ps.tag)) throw 'Injection';
+			query.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
+		} else {
+			query.andWhere(new Brackets(qb => {
+				for (const tags of ps.query!) {
+					qb.orWhere(new Brackets(qb => {
+						for (const tag of tags) {
+							if (!safeForSql(tag)) throw 'Injection';
+							qb.andWhere(`'{"${normalizeForSearch(tag)}"}' <@ note.tags`);
+						}
+					}));
+				}
+			}));
+		}
+	} catch (e) {
+		if (e === 'Injection') return [];
+		throw e;
 	}
 
 	if (ps.reply != null) {

From f85399e355685344d45efa49d220cf1508d0bfd5 Mon Sep 17 00:00:00 2001
From: Sandy Nicko Mac Corzeta <4186454+sandycorzeta@users.noreply.github.com>
Date: Sun, 23 May 2021 09:57:33 +0000
Subject: [PATCH 04/28] Add Indonesian to index language (#7528)

Co-authored-by: Sandy Nicko Mac Corzeta <sandynicko@windowslive.com>
---
 locales/index.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/locales/index.js b/locales/index.js
index 727e0e3848..35f9972ff7 100644
--- a/locales/index.js
+++ b/locales/index.js
@@ -21,6 +21,7 @@ const languages = [
 	'en-US',
 	'es-ES',
 	'fr-FR',
+	'id-ID',
 	'ja-JP',
 	'ja-KS',
 	'kab-KAB',

From c06091f78ab507085da3a1a4898b325a43e3201e Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 23 May 2021 21:14:29 +0900
Subject: [PATCH 05/28] Update README.md

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

diff --git a/README.md b/README.md
index 5cff3619fd..816765af67 100644
--- a/README.md
+++ b/README.md
@@ -99,6 +99,11 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
 
 To receive updates of this repo, follow [@repo@misskey.io](https://misskey.io/@repo) on fediverse.
 
+Related projects
+----------------------------------------------------------------
+- [misskey.js](https://github.com/misskey-dev/misskey.js) - Misskey SDK for JavaScript
+- [mfm.js](https://github.com/misskey-dev/mfm.js) - MFM parser
+
 :heart: Backers
 ----------------------------------------------------------------
 <!-- PATREON_START -->

From 35f075b8871f240aa94c4a21c77b9759ffd2c1b9 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 23 May 2021 21:28:41 +0900
Subject: [PATCH 06/28] :art:

---
 assets/about/banner.svg |  17 ++++++-----------
 assets/banner.afdesign  | Bin 65435 -> 73201 bytes
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/assets/about/banner.svg b/assets/about/banner.svg
index 31b6ca95e1..75308c0950 100644
--- a/assets/about/banner.svg
+++ b/assets/about/banner.svg
@@ -1,11 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg width="100%" height="100%" viewBox="0 0 1536 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
-    <g>
-        <g transform="matrix(3,0,0,2,2.27374e-13,0)">
-            <path d="M512,20.043C512,14.727 510.592,9.629 508.086,5.87C505.58,2.112 502.182,-0 498.638,0L13.362,0C9.818,-0 6.42,2.112 3.914,5.87C1.408,9.629 0,14.727 -0,20.043L0,491.957C0,497.273 1.408,502.371 3.914,506.13C6.42,509.888 9.818,512 13.362,512L498.638,512C502.182,512 505.58,509.888 508.086,506.13C510.592,502.371 512,497.273 512,491.957L512,20.043Z" style="fill:rgb(158,194,63);"/>
-        </g>
-        <g transform="matrix(1,0,0,1,9.6e-05,-50.9623)">
+<svg width="100%" height="100%" viewBox="0 0 1792 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+    <g transform="matrix(1,0,0,1,128,-57.1399)">
+        <g>
             <g transform="matrix(1,0,0,1,13.2723,-52.3253)">
                 <g id="_1f44d.svg" serif:id="1f44d.svg" transform="matrix(1.42513,0,0,1.42513,559.915,761.509)">
                     <g transform="matrix(1,0,0,1,-18,-18)">
@@ -61,14 +58,12 @@
                     </g>
                 </g>
             </g>
-            <g transform="matrix(0.517859,0,0,0.517859,635.428,379.428)">
-                <g transform="matrix(1.93103,-0,-0,1.93103,-1227.03,-634.276)">
-                    <use xlink:href="#_Image2" x="618.087" y="355.389" width="303.176px" height="221.833px" transform="matrix(0.997291,0,0,0.999247,0,0)"/>
-                </g>
+            <g transform="matrix(1,-0,-0,1,-128,57.1399)">
+                <use xlink:href="#_Image2" x="746.434" y="339.25" width="303.176px" height="221.833px" transform="matrix(0.997291,0,0,0.999247,0,0)"/>
             </g>
         </g>
     </g>
     <defs>
-        <image id="_Image2" width="304px" height="222px" xlink:href="data:image/png;base64,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"/>
+        <image id="_Image2" width="304px" height="222px" xlink:href="data:image/png;base64,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"/>
     </defs>
 </svg>
diff --git a/assets/banner.afdesign b/assets/banner.afdesign
index def3e884d3c1145f398944c81f8bae5723f14a0b..08b5c1b4a0b4720db0f3a7cab153edfa1a103ad1 100644
GIT binary patch
delta 18972
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
CS}B$Q

delta 11135
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


From c92744c3d36e371ddc8c6f9bbf9d64812ae5ace9 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 24 May 2021 05:50:45 +0900
Subject: [PATCH 07/28] Create SECURITY.md

---
 SECURITY.md | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 SECURITY.md

diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..2c026a5f33
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,9 @@
+# Reporting Security Issues
+
+If you discover a security issue in Misskey, please report it by sending an
+email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
+
+This will allow us to assess the risk, and make a fix available before we add a
+bug report to the GitHub repository.
+
+Thanks for helping make Misskey safe for everyone.

From ae2267220bb743808bffaf9a33f3bc6eed75a5b1 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 27 May 2021 17:15:08 +0900
Subject: [PATCH 08/28] wip #7533

---
 package.json                                  |   1 +
 src/client/components/drive.vue               |   4 +-
 src/client/components/follow-button.vue       |   2 +-
 src/client/components/notification.vue        |   2 +-
 src/client/components/notifications.vue       |   2 +-
 src/client/components/timeline.vue            |  20 +-
 src/client/init.ts                            |   8 +-
 src/client/instance.ts                        |  16 +-
 src/client/os.ts                              |  24 +-
 src/client/pages/instance/metrics.vue         |   4 +-
 src/client/pages/instance/queue.vue           |   2 +-
 src/client/pages/messaging/index.vue          |   2 +-
 src/client/pages/messaging/messaging-room.vue |   2 +-
 src/client/pages/reversi/game.vue             |   2 +-
 src/client/pages/reversi/index.vue            |   2 +-
 src/client/scripts/select-file.ts             |   4 +-
 src/client/scripts/stream.ts                  | 312 ------------------
 src/client/ui/_common_/common.vue             |   2 +-
 src/client/ui/chat/timeline.vue               |  20 +-
 src/client/widgets/job-queue.vue              |   2 +-
 src/client/widgets/photos.vue                 |   2 +-
 src/client/widgets/server-metric/index.vue    |   2 +-
 yarn.lock                                     |  18 +-
 23 files changed, 69 insertions(+), 386 deletions(-)
 delete mode 100644 src/client/scripts/stream.ts

diff --git a/package.json b/package.json
index 4f01c78817..610678989f 100644
--- a/package.json
+++ b/package.json
@@ -174,6 +174,7 @@
 		"markdown-it-anchor": "7.1.0",
 		"matter-js": "0.17.1",
 		"mfm-js": "0.16.4",
+		"misskey-js": "0.0.2",
 		"mocha": "8.4.0",
 		"moji": "0.5.1",
 		"ms": "2.1.3",
diff --git a/src/client/components/drive.vue b/src/client/components/drive.vue
index 06f9cf7806..ca637e3f3d 100644
--- a/src/client/components/drive.vue
+++ b/src/client/components/drive.vue
@@ -139,7 +139,7 @@ export default defineComponent({
 			});
 		}
 
-		this.connection = os.stream.useSharedConnection('drive');
+		this.connection = os.stream.useChannel('drive');
 
 		this.connection.on('fileCreated', this.onStreamDriveFileCreated);
 		this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
@@ -301,7 +301,7 @@ export default defineComponent({
 				}
 			}).then(({ canceled, result: url }) => {
 				if (canceled) return;
-				os.api('drive/files/upload_from_url', {
+				os.api('drive/files/upload-from-url', {
 					url: url,
 					folderId: this.folder ? this.folder.id : undefined
 				});
diff --git a/src/client/components/follow-button.vue b/src/client/components/follow-button.vue
index 7199183c66..49bf678491 100644
--- a/src/client/components/follow-button.vue
+++ b/src/client/components/follow-button.vue
@@ -71,7 +71,7 @@ export default defineComponent({
 	},
 
 	mounted() {
-		this.connection = os.stream.useSharedConnection('main');
+		this.connection = os.stream.useChannel('main');
 
 		this.connection.on('follow', this.onFollowChange);
 		this.connection.on('unfollow', this.onFollowChange);
diff --git a/src/client/components/notification.vue b/src/client/components/notification.vue
index 9badd7a708..c7063b0aa2 100644
--- a/src/client/components/notification.vue
+++ b/src/client/components/notification.vue
@@ -109,7 +109,7 @@ export default defineComponent({
 
 			this.readObserver.observe(this.$el);
 
-			this.connection = os.stream.useSharedConnection('main');
+			this.connection = os.stream.useChannel('main');
 			this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el));
 		}
 	},
diff --git a/src/client/components/notifications.vue b/src/client/components/notifications.vue
index 161419f891..6caf8eb8e3 100644
--- a/src/client/components/notifications.vue
+++ b/src/client/components/notifications.vue
@@ -87,7 +87,7 @@ export default defineComponent({
 	},
 
 	mounted() {
-		this.connection = os.stream.useSharedConnection('main');
+		this.connection = os.stream.useChannel('main');
 		this.connection.on('notification', this.onNotification);
 	},
 
diff --git a/src/client/components/timeline.vue b/src/client/components/timeline.vue
index 753eba2ba1..c21e1ec2a6 100644
--- a/src/client/components/timeline.vue
+++ b/src/client/components/timeline.vue
@@ -92,33 +92,33 @@ export default defineComponent({
 			this.query = {
 				antennaId: this.antenna
 			};
-			this.connection = os.stream.connectToChannel('antenna', {
+			this.connection = os.stream.useChannel('antenna', {
 				antennaId: this.antenna
 			});
 			this.connection.on('note', prepend);
 		} else if (this.src == 'home') {
 			endpoint = 'notes/timeline';
-			this.connection = os.stream.useSharedConnection('homeTimeline');
+			this.connection = os.stream.useChannel('homeTimeline');
 			this.connection.on('note', prepend);
 
-			this.connection2 = os.stream.useSharedConnection('main');
+			this.connection2 = os.stream.useChannel('main');
 			this.connection2.on('follow', onChangeFollowing);
 			this.connection2.on('unfollow', onChangeFollowing);
 		} else if (this.src == 'local') {
 			endpoint = 'notes/local-timeline';
-			this.connection = os.stream.useSharedConnection('localTimeline');
+			this.connection = os.stream.useChannel('localTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'social') {
 			endpoint = 'notes/hybrid-timeline';
-			this.connection = os.stream.useSharedConnection('hybridTimeline');
+			this.connection = os.stream.useChannel('hybridTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'global') {
 			endpoint = 'notes/global-timeline';
-			this.connection = os.stream.useSharedConnection('globalTimeline');
+			this.connection = os.stream.useChannel('globalTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'mentions') {
 			endpoint = 'notes/mentions';
-			this.connection = os.stream.useSharedConnection('main');
+			this.connection = os.stream.useChannel('main');
 			this.connection.on('mention', prepend);
 		} else if (this.src == 'directs') {
 			endpoint = 'notes/mentions';
@@ -130,14 +130,14 @@ export default defineComponent({
 					prepend(note);
 				}
 			};
-			this.connection = os.stream.useSharedConnection('main');
+			this.connection = os.stream.useChannel('main');
 			this.connection.on('mention', onNote);
 		} else if (this.src == 'list') {
 			endpoint = 'notes/user-list-timeline';
 			this.query = {
 				listId: this.list
 			};
-			this.connection = os.stream.connectToChannel('userList', {
+			this.connection = os.stream.useChannel('userList', {
 				listId: this.list
 			});
 			this.connection.on('note', prepend);
@@ -148,7 +148,7 @@ export default defineComponent({
 			this.query = {
 				channelId: this.channel
 			};
-			this.connection = os.stream.connectToChannel('channel', {
+			this.connection = os.stream.useChannel('channel', {
 				channelId: this.channel
 			});
 			this.connection.on('note', prepend);
diff --git a/src/client/init.ts b/src/client/init.ts
index a4465d75c3..19b95fc50e 100644
--- a/src/client/init.ts
+++ b/src/client/init.ts
@@ -163,8 +163,6 @@ fetchInstance().then(() => {
 	initializeSw();
 });
 
-stream.init($i);
-
 const app = createApp(await (
 	window.location.search === '?zen' ? import('@client/ui/zen.vue') :
 	!$i                               ? import('@client/ui/visitor.vue') :
@@ -296,7 +294,7 @@ if ($i) {
 		}
 	}
 
-	const main = stream.useSharedConnection('main', 'System');
+	const main = stream.useChannel('main', 'System');
 
 	// 自分の情報が更新されたとき
 	main.on('meUpdated', i => {
@@ -358,10 +356,6 @@ if ($i) {
 		sound.play('channel');
 	});
 
-	main.on('readAllAnnouncements', () => {
-		updateAccount({ hasUnreadAnnouncement: false });
-	});
-
 	// トークンが再生成されたとき
 	// このままではMisskeyが利用できないので強制的にサインアウトさせる
 	main.on('myTokenRegenerated', () => {
diff --git a/src/client/instance.ts b/src/client/instance.ts
index 024ff1acbd..04d3353208 100644
--- a/src/client/instance.ts
+++ b/src/client/instance.ts
@@ -1,26 +1,14 @@
 import { computed, reactive } from 'vue';
+import * as Misskey from 'misskey-js';
 import { api } from './os';
 
 // TODO: 他のタブと永続化されたstateを同期
 
-export type Instance = {
-	emojis: {
-		category: string;
-	}[];
-	ads: {
-		id: string;
-		ratio: number;
-		place: string;
-		url: string;
-		imageUrl: string;
-	}[];
-};
-
 const data = localStorage.getItem('instance');
 
 // TODO: instanceをリアクティブにするかは再考の余地あり
 
-export const instance: Instance = reactive(data ? JSON.parse(data) : {
+export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : {
 	// TODO: set default values
 });
 
diff --git a/src/client/os.ts b/src/client/os.ts
index b159cf509d..e6355b45b8 100644
--- a/src/client/os.ts
+++ b/src/client/os.ts
@@ -3,16 +3,16 @@
 import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
 import { EventEmitter } from 'eventemitter3';
 import insertTextAtCursor from 'insert-text-at-cursor';
+import * as Misskey from 'misskey-js';
 import * as Sentry from '@sentry/browser';
-import Stream from '@client/scripts/stream';
-import { apiUrl, debug } from '@client/config';
+import { apiUrl, debug, url } from '@client/config';
 import MkPostFormDialog from '@client/components/post-form-dialog.vue';
 import MkWaitingDialog from '@client/components/waiting-dialog.vue';
 import { resolve } from '@client/router';
 import { $i } from '@client/account';
 import { defaultStore } from '@client/store';
 
-export const stream = markRaw(new Stream());
+export const stream = markRaw(new Misskey.Stream(url, $i));
 
 export const pendingApiRequestsCount = ref(0);
 let apiRequestsCount = 0; // for debug
@@ -20,7 +20,11 @@ export const apiRequests = ref([]); // for debug
 
 export const windows = new Map();
 
-export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) {
+const apiClient = new Misskey.api.APIClient({
+	origin: url,
+});
+
+export const api = ((endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) => {
 	pendingApiRequestsCount.value++;
 
 	const onFinally = () => {
@@ -90,17 +94,15 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
 	promise.then(onFinally, onFinally);
 
 	return promise;
-}
+}) as typeof apiClient.request;
 
-export function apiWithDialog(
+export const apiWithDialog = ((
 	endpoint: string,
 	data: Record<string, any> = {},
 	token?: string | null | undefined,
-	onSuccess?: (res: any) => void,
-	onFailure?: (e: Error) => void,
-) {
+) => {
 	const promise = api(endpoint, data, token);
-	promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => {
+	promiseDialog(promise, null, (e) => {
 		dialog({
 			type: 'error',
 			text: e.message + '\n' + (e as any).id,
@@ -108,7 +110,7 @@ export function apiWithDialog(
 	});
 
 	return promise;
-}
+}) as typeof api;
 
 export function promiseDialog<T extends Promise<any>>(
 	promise: T,
diff --git a/src/client/pages/instance/metrics.vue b/src/client/pages/instance/metrics.vue
index 18cfe5eee2..407cce9e7f 100644
--- a/src/client/pages/instance/metrics.vue
+++ b/src/client/pages/instance/metrics.vue
@@ -90,7 +90,7 @@ export default defineComponent({
 			stats: null,
 			serverInfo: null,
 			connection: null,
-			queueConnection: os.stream.useSharedConnection('queueStats'),
+			queueConnection: os.stream.useChannel('queueStats'),
 			memUsage: 0,
 			chartCpuMem: null,
 			chartNet: null,
@@ -121,7 +121,7 @@ export default defineComponent({
 		os.api('admin/server-info', {}).then(res => {
 			this.serverInfo = res;
 
-			this.connection = os.stream.useSharedConnection('serverStats');
+			this.connection = os.stream.useChannel('serverStats');
 			this.connection.on('stats', this.onStats);
 			this.connection.on('statsLog', this.onStatsLog);
 			this.connection.send('requestLog', {
diff --git a/src/client/pages/instance/queue.vue b/src/client/pages/instance/queue.vue
index 2dccf48d31..8f56fd74bf 100644
--- a/src/client/pages/instance/queue.vue
+++ b/src/client/pages/instance/queue.vue
@@ -35,7 +35,7 @@ export default defineComponent({
 				title: this.$ts.jobQueue,
 				icon: 'fas fa-clipboard-list',
 			},
-			connection: os.stream.useSharedConnection('queueStats'),
+			connection: os.stream.useChannel('queueStats'),
 		}
 	},
 
diff --git a/src/client/pages/messaging/index.vue b/src/client/pages/messaging/index.vue
index 9f3323f629..832cce5ab9 100644
--- a/src/client/pages/messaging/index.vue
+++ b/src/client/pages/messaging/index.vue
@@ -63,7 +63,7 @@ export default defineComponent({
 	},
 
 	mounted() {
-		this.connection = os.stream.useSharedConnection('messagingIndex');
+		this.connection = os.stream.useChannel('messagingIndex');
 
 		this.connection.on('message', this.onMessage);
 		this.connection.on('read', this.onRead);
diff --git a/src/client/pages/messaging/messaging-room.vue b/src/client/pages/messaging/messaging-room.vue
index 44bfd6c51d..f1d55ee288 100644
--- a/src/client/pages/messaging/messaging-room.vue
+++ b/src/client/pages/messaging/messaging-room.vue
@@ -141,7 +141,7 @@ const Component = defineComponent({
 				this.group = group;
 			}
 
-			this.connection = os.stream.connectToChannel('messaging', {
+			this.connection = os.stream.useChannel('messaging', {
 				otherparty: this.user ? this.user.id : undefined,
 				group: this.group ? this.group.id : undefined,
 			});
diff --git a/src/client/pages/reversi/game.vue b/src/client/pages/reversi/game.vue
index 62c99d7755..dc4d11ca4a 100644
--- a/src/client/pages/reversi/game.vue
+++ b/src/client/pages/reversi/game.vue
@@ -61,7 +61,7 @@ export default defineComponent({
 				if (this.connection) {
 					this.connection.dispose();
 				}
-				this.connection = os.stream.connectToChannel('gamesReversiGame', {
+				this.connection = os.stream.useChannel('gamesReversiGame', {
 					gameId: this.game.id
 				});
 				this.connection.on('started', this.onStarted);
diff --git a/src/client/pages/reversi/index.vue b/src/client/pages/reversi/index.vue
index 37126fca10..dd329084a8 100644
--- a/src/client/pages/reversi/index.vue
+++ b/src/client/pages/reversi/index.vue
@@ -92,7 +92,7 @@ export default defineComponent({
 
 	mounted() {
 		if (this.$i) {
-			this.connection = os.stream.useSharedConnection('gamesReversi');
+			this.connection = os.stream.useChannel('gamesReversi');
 
 			this.connection.on('invited', this.onInvited);
 
diff --git a/src/client/scripts/select-file.ts b/src/client/scripts/select-file.ts
index c193e7dc71..b8039fb670 100644
--- a/src/client/scripts/select-file.ts
+++ b/src/client/scripts/select-file.ts
@@ -47,7 +47,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
 
 				const marker = Math.random().toString(); // TODO: UUIDとか使う
 
-				const connection = os.stream.useSharedConnection('main');
+				const connection = os.stream.useChannel('main');
 				connection.on('urlUploadFinished', data => {
 					if (data.marker === marker) {
 						res(multiple ? [data.file] : data.file);
@@ -55,7 +55,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
 					}
 				});
 
-				os.api('drive/files/upload_from_url', {
+				os.api('drive/files/upload-from-url', {
 					url: url,
 					marker
 				});
diff --git a/src/client/scripts/stream.ts b/src/client/scripts/stream.ts
deleted file mode 100644
index 065059221d..0000000000
--- a/src/client/scripts/stream.ts
+++ /dev/null
@@ -1,312 +0,0 @@
-import autobind from 'autobind-decorator';
-import { EventEmitter } from 'eventemitter3';
-import ReconnectingWebsocket from 'reconnecting-websocket';
-import { markRaw } from 'vue';
-import { debug, wsUrl } from '@client/config';
-import { query as urlQuery } from '../../prelude/url';
-
-/**
- * Misskey stream connection
- */
-export default class Stream extends EventEmitter {
-	private stream: ReconnectingWebsocket;
-	public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
-	private sharedConnectionPools: Pool[] = [];
-	private sharedConnections: SharedConnection[] = [];
-	private nonSharedConnections: NonSharedConnection[] = [];
-
-	@autobind
-	public init(user): void {
-		const query = urlQuery({
-			i: user?.token,
-			_t: Date.now(),
-		});
-
-		this.stream = new ReconnectingWebsocket(`${wsUrl}?${query}`, '', { minReconnectionDelay: 1 }); // https://github.com/pladaria/reconnecting-websocket/issues/91
-		this.stream.addEventListener('open', this.onOpen);
-		this.stream.addEventListener('close', this.onClose);
-		this.stream.addEventListener('message', this.onMessage);
-	}
-
-	@autobind
-	public useSharedConnection(channel: string, name?: string): SharedConnection {
-		let pool = this.sharedConnectionPools.find(p => p.channel === channel);
-
-		if (pool == null) {
-			pool = new Pool(this, channel);
-			this.sharedConnectionPools.push(pool);
-		}
-
-		const connection = markRaw(new SharedConnection(this, channel, pool, name));
-		this.sharedConnections.push(connection);
-		return connection;
-	}
-
-	@autobind
-	public removeSharedConnection(connection: SharedConnection) {
-		this.sharedConnections = this.sharedConnections.filter(c => c !== connection);
-	}
-
-	@autobind
-	public removeSharedConnectionPool(pool: Pool) {
-		this.sharedConnectionPools = this.sharedConnectionPools.filter(p => p !== pool);
-	}
-
-	@autobind
-	public connectToChannel(channel: string, params?: any): NonSharedConnection {
-		const connection = markRaw(new NonSharedConnection(this, channel, params));
-		this.nonSharedConnections.push(connection);
-		return connection;
-	}
-
-	@autobind
-	public disconnectToChannel(connection: NonSharedConnection) {
-		this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection);
-	}
-
-	/**
-	 * Callback of when open connection
-	 */
-	@autobind
-	private onOpen() {
-		const isReconnect = this.state === 'reconnecting';
-
-		this.state = 'connected';
-		this.emit('_connected_');
-
-		// チャンネル再接続
-		if (isReconnect) {
-			for (const p of this.sharedConnectionPools)
-				p.connect();
-			for (const c of this.nonSharedConnections)
-				c.connect();
-		}
-	}
-
-	/**
-	 * Callback of when close connection
-	 */
-	@autobind
-	private onClose() {
-		if (this.state === 'connected') {
-			this.state = 'reconnecting';
-			this.emit('_disconnected_');
-		}
-	}
-
-	/**
-	 * Callback of when received a message from connection
-	 */
-	@autobind
-	private onMessage(message) {
-		const { type, body } = JSON.parse(message.data);
-
-		if (type === 'channel') {
-			const id = body.id;
-
-			let connections: Connection[];
-
-			connections = this.sharedConnections.filter(c => c.id === id);
-
-			if (connections.length === 0) {
-				connections = [this.nonSharedConnections.find(c => c.id === id)];
-			}
-
-			for (const c of connections.filter(c => c != null)) {
-				c.emit(body.type, Object.freeze(body.body));
-				if (debug) c.inCount++;
-			}
-		} else {
-			this.emit(type, Object.freeze(body));
-		}
-	}
-
-	/**
-	 * Send a message to connection
-	 */
-	@autobind
-	public send(typeOrPayload, payload?) {
-		const data = payload === undefined ? typeOrPayload : {
-			type: typeOrPayload,
-			body: payload
-		};
-
-		this.stream.send(JSON.stringify(data));
-	}
-
-	/**
-	 * Close this connection
-	 */
-	@autobind
-	public close() {
-		this.stream.removeEventListener('open', this.onOpen);
-		this.stream.removeEventListener('message', this.onMessage);
-	}
-}
-
-let idCounter = 0;
-
-class Pool {
-	public channel: string;
-	public id: string;
-	protected stream: Stream;
-	public users = 0;
-	private disposeTimerId: any;
-	private isConnected = false;
-
-	constructor(stream: Stream, channel: string) {
-		this.channel = channel;
-		this.stream = stream;
-
-		this.id = (++idCounter).toString();
-
-		this.stream.on('_disconnected_', this.onStreamDisconnected);
-	}
-
-	@autobind
-	private onStreamDisconnected() {
-		this.isConnected = false;
-	}
-
-	@autobind
-	public inc() {
-		if (this.users === 0 && !this.isConnected) {
-			this.connect();
-		}
-
-		this.users++;
-
-		// タイマー解除
-		if (this.disposeTimerId) {
-			clearTimeout(this.disposeTimerId);
-			this.disposeTimerId = null;
-		}
-	}
-
-	@autobind
-	public dec() {
-		this.users--;
-
-		// そのコネクションの利用者が誰もいなくなったら
-		if (this.users === 0) {
-			// また直ぐに再利用される可能性があるので、一定時間待ち、
-			// 新たな利用者が現れなければコネクションを切断する
-			this.disposeTimerId = setTimeout(() => {
-				this.disconnect();
-			}, 3000);
-		}
-	}
-
-	@autobind
-	public connect() {
-		if (this.isConnected) return;
-		this.isConnected = true;
-		this.stream.send('connect', {
-			channel: this.channel,
-			id: this.id
-		});
-	}
-
-	@autobind
-	private disconnect() {
-		this.stream.off('_disconnected_', this.onStreamDisconnected);
-		this.stream.send('disconnect', { id: this.id });
-		this.stream.removeSharedConnectionPool(this);
-	}
-}
-
-abstract class Connection extends EventEmitter {
-	public channel: string;
-	protected stream: Stream;
-	public abstract id: string;
-
-	public name?: string; // for debug
-	public inCount: number = 0; // for debug
-	public outCount: number = 0; // for debug
-
-	constructor(stream: Stream, channel: string, name?: string) {
-		super();
-
-		this.stream = stream;
-		this.channel = channel;
-		this.name = name;
-	}
-
-	@autobind
-	public send(id: string, typeOrPayload, payload?) {
-		const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
-		const body = payload === undefined ? typeOrPayload.body : payload;
-
-		this.stream.send('ch', {
-			id: id,
-			type: type,
-			body: body
-		});
-
-		if (debug) this.outCount++;
-	}
-
-	public abstract dispose(): void;
-}
-
-class SharedConnection extends Connection {
-	private pool: Pool;
-
-	public get id(): string {
-		return this.pool.id;
-	}
-
-	constructor(stream: Stream, channel: string, pool: Pool, name?: string) {
-		super(stream, channel, name);
-
-		this.pool = pool;
-		this.pool.inc();
-	}
-
-	@autobind
-	public send(typeOrPayload, payload?) {
-		super.send(this.pool.id, typeOrPayload, payload);
-	}
-
-	@autobind
-	public dispose() {
-		this.pool.dec();
-		this.removeAllListeners();
-		this.stream.removeSharedConnection(this);
-	}
-}
-
-class NonSharedConnection extends Connection {
-	public id: string;
-	protected params: any;
-
-	constructor(stream: Stream, channel: string, params?: any) {
-		super(stream, channel);
-
-		this.params = params;
-		this.id = (++idCounter).toString();
-
-		this.connect();
-	}
-
-	@autobind
-	public connect() {
-		this.stream.send('connect', {
-			channel: this.channel,
-			id: this.id,
-			params: this.params
-		});
-	}
-
-	@autobind
-	public send(typeOrPayload, payload?) {
-		super.send(this.id, typeOrPayload, payload);
-	}
-
-	@autobind
-	public dispose() {
-		this.removeAllListeners();
-		this.stream.send('disconnect', { id: this.id });
-		this.stream.disconnectToChannel(this);
-	}
-}
diff --git a/src/client/ui/_common_/common.vue b/src/client/ui/_common_/common.vue
index 785b1631db..1e825e0fe0 100644
--- a/src/client/ui/_common_/common.vue
+++ b/src/client/ui/_common_/common.vue
@@ -43,7 +43,7 @@ export default defineComponent({
 		};
 
 		if ($i) {
-			const connection = stream.useSharedConnection('main', 'UI');
+			const connection = stream.useChannel('main', 'UI');
 			connection.on('notification', onNotification);
 		}
 
diff --git a/src/client/ui/chat/timeline.vue b/src/client/ui/chat/timeline.vue
index 13032cce09..2245a9d8a5 100644
--- a/src/client/ui/chat/timeline.vue
+++ b/src/client/ui/chat/timeline.vue
@@ -121,33 +121,33 @@ export default defineComponent({
 			this.query = {
 				antennaId: this.antenna
 			};
-			this.connection = os.stream.connectToChannel('antenna', {
+			this.connection = os.stream.useChannel('antenna', {
 				antennaId: this.antenna
 			});
 			this.connection.on('note', prepend);
 		} else if (this.src == 'home') {
 			endpoint = 'notes/timeline';
-			this.connection = os.stream.useSharedConnection('homeTimeline');
+			this.connection = os.stream.useChannel('homeTimeline');
 			this.connection.on('note', prepend);
 
-			this.connection2 = os.stream.useSharedConnection('main');
+			this.connection2 = os.stream.useChannel('main');
 			this.connection2.on('follow', onChangeFollowing);
 			this.connection2.on('unfollow', onChangeFollowing);
 		} else if (this.src == 'local') {
 			endpoint = 'notes/local-timeline';
-			this.connection = os.stream.useSharedConnection('localTimeline');
+			this.connection = os.stream.useChannel('localTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'social') {
 			endpoint = 'notes/hybrid-timeline';
-			this.connection = os.stream.useSharedConnection('hybridTimeline');
+			this.connection = os.stream.useChannel('hybridTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'global') {
 			endpoint = 'notes/global-timeline';
-			this.connection = os.stream.useSharedConnection('globalTimeline');
+			this.connection = os.stream.useChannel('globalTimeline');
 			this.connection.on('note', prepend);
 		} else if (this.src == 'mentions') {
 			endpoint = 'notes/mentions';
-			this.connection = os.stream.useSharedConnection('main');
+			this.connection = os.stream.useChannel('main');
 			this.connection.on('mention', prepend);
 		} else if (this.src == 'directs') {
 			endpoint = 'notes/mentions';
@@ -159,14 +159,14 @@ export default defineComponent({
 					prepend(note);
 				}
 			};
-			this.connection = os.stream.useSharedConnection('main');
+			this.connection = os.stream.useChannel('main');
 			this.connection.on('mention', onNote);
 		} else if (this.src == 'list') {
 			endpoint = 'notes/user-list-timeline';
 			this.query = {
 				listId: this.list
 			};
-			this.connection = os.stream.connectToChannel('userList', {
+			this.connection = os.stream.useChannel('userList', {
 				listId: this.list
 			});
 			this.connection.on('note', prepend);
@@ -178,7 +178,7 @@ export default defineComponent({
 			this.query = {
 				channelId: this.channel
 			};
-			this.connection = os.stream.connectToChannel('channel', {
+			this.connection = os.stream.useChannel('channel', {
 				channelId: this.channel
 			});
 			this.connection.on('note', prepend);
diff --git a/src/client/widgets/job-queue.vue b/src/client/widgets/job-queue.vue
index 31a322e6e2..162ffe9c89 100644
--- a/src/client/widgets/job-queue.vue
+++ b/src/client/widgets/job-queue.vue
@@ -65,7 +65,7 @@ export default defineComponent({
 	extends: widget,
 	data() {
 		return {
-			connection: os.stream.useSharedConnection('queueStats'),
+			connection: os.stream.useChannel('queueStats'),
 			inbox: {
 				activeSincePrevTick: 0,
 				active: 0,
diff --git a/src/client/widgets/photos.vue b/src/client/widgets/photos.vue
index 65843385b6..7f6fa82722 100644
--- a/src/client/widgets/photos.vue
+++ b/src/client/widgets/photos.vue
@@ -48,7 +48,7 @@ export default defineComponent({
 		};
 	},
 	mounted() {
-		this.connection = os.stream.useSharedConnection('main');
+		this.connection = os.stream.useChannel('main');
 
 		this.connection.on('driveFileCreated', this.onDriveFileCreated);
 
diff --git a/src/client/widgets/server-metric/index.vue b/src/client/widgets/server-metric/index.vue
index 6331b5bdf1..2398e9920f 100644
--- a/src/client/widgets/server-metric/index.vue
+++ b/src/client/widgets/server-metric/index.vue
@@ -63,7 +63,7 @@ export default defineComponent({
 		os.api('server-info', {}).then(res => {
 			this.meta = res;
 		});
-		this.connection = os.stream.useSharedConnection('serverStats');
+		this.connection = os.stream.useChannel('serverStats');
 	},
 	unmounted() {
 		this.connection.dispose();
diff --git a/yarn.lock b/yarn.lock
index 9e32e6e913..9296aafc4e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1290,7 +1290,7 @@
     "@vue/compiler-dom" "3.0.11"
     "@vue/shared" "3.0.11"
 
-"@vue/reactivity@3.0.11":
+"@vue/reactivity@3.0.11", "@vue/reactivity@^3.0.11":
   version "3.0.11"
   resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.11.tgz#07b588349fd05626b17f3500cbef7d4bdb4dbd0b"
   integrity sha512-SKM3YKxtXHBPMf7yufXeBhCZ4XZDKP9/iXeQSC8bBO3ivBuzAi4aZi0bNoeE2IF2iGfP/AHEt1OU4ARj4ao/Xw==
@@ -1899,7 +1899,7 @@ atob@^2.1.2:
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
 
-autobind-decorator@2.4.0:
+autobind-decorator@2.4.0, autobind-decorator@^2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-2.4.0.tgz#ea9e1c98708cf3b5b356f7cf9f10f265ff18239c"
   integrity sha512-OGYhWUO72V6DafbF8PM8rm3EPbfuyMZcJhtm5/n26IDwO18pohE4eNazLoCGhPiXOCD0gEGmrbU3849QvM8bbw==
@@ -4203,7 +4203,7 @@ event-target-shim@^5.0.0:
   resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
   integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
 
-eventemitter3@4.0.7:
+eventemitter3@4.0.7, eventemitter3@^4.0.7:
   version "4.0.7"
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
   integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
@@ -6977,6 +6977,16 @@ minizlib@^2.0.0, minizlib@^2.1.1:
     minipass "^3.0.0"
     yallist "^4.0.0"
 
+misskey-js@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/misskey-js/-/misskey-js-0.0.2.tgz#233d62e5a326a00dd72f36d63436e6584c8076f2"
+  integrity sha512-gsq3E9lUepNapK4i/3mmqjobQV6gYlgO1O1rQt401ot3LCYlcaLhlUrwBOFtI+ALMGKgwRgkLlDQhcWgAfHHuQ==
+  dependencies:
+    "@vue/reactivity" "^3.0.11"
+    autobind-decorator "^2.4.0"
+    eventemitter3 "^4.0.7"
+    reconnecting-websocket "^4.4.0"
+
 mixin-deep@^1.2.0:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -9072,7 +9082,7 @@ rechoir@^0.7.0:
   dependencies:
     resolve "^1.9.0"
 
-reconnecting-websocket@4.4.0:
+reconnecting-websocket@4.4.0, reconnecting-websocket@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
   integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==

From 466c083233d5f44cfcdfdfa02d8a6bb090382400 Mon Sep 17 00:00:00 2001
From: rinsuki <428rinsuki+git@gmail.com>
Date: Thu, 27 May 2021 22:40:48 +0900
Subject: [PATCH 09/28] =?UTF-8?q?=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?=
 =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=82=92proxy=E3=81=AB=E9=80=9A?=
 =?UTF-8?q?=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=20(#7526)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/client/scripts/get-static-image-url.ts | 5 +++++
 src/misc/populate-emojis.ts                | 7 ++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/client/scripts/get-static-image-url.ts b/src/client/scripts/get-static-image-url.ts
index e2728d73f4..92c31914c7 100644
--- a/src/client/scripts/get-static-image-url.ts
+++ b/src/client/scripts/get-static-image-url.ts
@@ -3,6 +3,11 @@ import * as url from '../../prelude/url';
 
 export function getStaticImageUrl(baseUrl: string): string {
 	const u = new URL(baseUrl);
+	if (u.href.startsWith(`${instanceUrl}/proxy/`)) {
+		// もう既にproxyっぽそうだったらsearchParams付けるだけ
+		u.searchParams.set('static', '1');
+		return u.href;
+	}
 	const dummy = `${u.host}${u.pathname}`;	// 拡張子がないとキャッシュしてくれないCDNがあるので
 	return `${instanceUrl}/proxy/${dummy}?${url.query({
 		url: u.href,
diff --git a/src/misc/populate-emojis.ts b/src/misc/populate-emojis.ts
index 8052c71489..a3f67ccb98 100644
--- a/src/misc/populate-emojis.ts
+++ b/src/misc/populate-emojis.ts
@@ -5,6 +5,8 @@ import { Note } from '../models/entities/note';
 import { Cache } from './cache';
 import { isSelfHost, toPunyNullable } from './convert-host';
 import { decodeReaction } from './reaction-lib';
+import config from '@/config';
+import { query } from '@/prelude/url';
 
 const cache = new Cache<Emoji | null>(1000 * 60 * 60 * 12);
 
@@ -59,9 +61,12 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
 
 	if (emoji == null) return null;
 
+	const isLocal = emojiName.endsWith('@.');
+	const url = isLocal ? emoji.url : `${config.url}/proxy/image.png?${query({url: emoji.url})}`;
+
 	return {
 		name: emojiName,
-		url: emoji.url,
+		url,
 	};
 }
 

From db3724cf33c402d66700f89b319b423887466757 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 28 May 2021 09:34:42 +0900
Subject: [PATCH 10/28] improve types

---
 src/server/api/define.ts                      |  7 +++++--
 .../api/endpoints/gallery/posts/create.ts     |  3 ++-
 .../api/endpoints/gallery/posts/update.ts     |  3 ++-
 src/services/chart/core.ts                    | 21 +++++++++----------
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/server/api/define.ts b/src/server/api/define.ts
index 432d5017e8..cba69cfdc4 100644
--- a/src/server/api/define.ts
+++ b/src/server/api/define.ts
@@ -5,6 +5,8 @@ import { ApiError } from './error';
 import { SchemaType } from '@/misc/schema';
 import { AccessToken } from '../../models/entities/access-token';
 
+type NonOptional<T> = T extends undefined ? never : T;
+
 type SimpleUserInfo = {
 	id: ILocalUser['id'];
 	host: ILocalUser['host'];
@@ -17,11 +19,12 @@ type SimpleUserInfo = {
 	isSilenced: ILocalUser['isSilenced'];
 };
 
-// TODO: defaultが設定されている場合はその型も考慮する
 type Params<T extends IEndpointMeta> = {
 	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
 		? ReturnType<NonNullable<T['params']>[P]['transform']>
-		: ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0];
+		: NonNullable<T['params']>[P]['default'] extends null | number | string
+			? NonOptional<ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0]>
+			: ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0];
 };
 
 export type Response = Record<string, any> | void;
diff --git a/src/server/api/endpoints/gallery/posts/create.ts b/src/server/api/endpoints/gallery/posts/create.ts
index d1ae68b126..ed24a45f88 100644
--- a/src/server/api/endpoints/gallery/posts/create.ts
+++ b/src/server/api/endpoints/gallery/posts/create.ts
@@ -6,6 +6,7 @@ import { DriveFiles, GalleryPosts } from '../../../../../models';
 import { genId } from '../../../../../misc/gen-id';
 import { GalleryPost } from '../../../../../models/entities/gallery-post';
 import { ApiError } from '../../../error';
+import { DriveFile } from '@/models/entities/drive-file';
 
 export const meta = {
 	tags: ['gallery'],
@@ -55,7 +56,7 @@ export default define(meta, async (ps, user) => {
 			id: fileId,
 			userId: user.id
 		})
-	))).filter(file => file != null);
+	))).filter((file): file is DriveFile => file != null);
 
 	if (files.length === 0) {
 		throw new Error();
diff --git a/src/server/api/endpoints/gallery/posts/update.ts b/src/server/api/endpoints/gallery/posts/update.ts
index c8bb8d48c9..d9176ea407 100644
--- a/src/server/api/endpoints/gallery/posts/update.ts
+++ b/src/server/api/endpoints/gallery/posts/update.ts
@@ -5,6 +5,7 @@ import { ID } from '../../../../../misc/cafy-id';
 import { DriveFiles, GalleryPosts } from '../../../../../models';
 import { GalleryPost } from '../../../../../models/entities/gallery-post';
 import { ApiError } from '../../../error';
+import { DriveFile } from '@/models/entities/drive-file';
 
 export const meta = {
 	tags: ['gallery'],
@@ -58,7 +59,7 @@ export default define(meta, async (ps, user) => {
 			id: fileId,
 			userId: user.id
 		})
-	))).filter(file => file != null);
+	))).filter((file): file is DriveFile => file != null);
 
 	if (files.length === 0) {
 		throw new Error();
diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts
index d956d33bd7..4a554daa78 100644
--- a/src/services/chart/core.ts
+++ b/src/services/chart/core.ts
@@ -93,7 +93,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private static convertFlattenColumnsToObject(x: Record<string, number>) {
+	private static convertFlattenColumnsToObject(x: Record<string, any>): Record<string, any> {
 		const obj = {} as any;
 		for (const k of Object.keys(x).filter(k => k.startsWith(Chart.columnPrefix))) {
 			// now k is ___x_y_z
@@ -285,8 +285,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 		const latest = await this.getLatestLog(group);
 
 		if (latest != null) {
-			const obj = Chart.convertFlattenColumnsToObject(
-				latest as Record<string, any>);
+			const obj = Chart.convertFlattenColumnsToObject(latest) as T;
 
 			// 空ログデータを作成
 			data = this.getNewLog(obj);
@@ -474,13 +473,13 @@ export default abstract class Chart<T extends Record<string, any>> {
 				const log = logs.find(l => isTimeSame(new Date(l.date * 1000), current));
 
 				if (log) {
-					const data = Chart.convertFlattenColumnsToObject(log as Record<string, any>);
-					chart.unshift(Chart.countUniqueFields(data));
+					const data = Chart.convertFlattenColumnsToObject(log);
+					chart.unshift(Chart.countUniqueFields(data) as T);
 				} else {
 					// 隙間埋め
 					const latest = logs.find(l => isTimeBefore(new Date(l.date * 1000), current));
-					const data = latest ? Chart.convertFlattenColumnsToObject(latest as Record<string, any>) : null;
-					chart.unshift(Chart.countUniqueFields(this.getNewLog(data)));
+					const data = latest ? Chart.convertFlattenColumnsToObject(latest) as T : null;
+					chart.unshift(Chart.countUniqueFields(this.getNewLog(data)) as T);
 				}
 			}
 		} else if (span === 'day') {
@@ -497,14 +496,14 @@ export default abstract class Chart<T extends Record<string, any>> {
 
 				if (log) {
 					if (logsForEachDays[currentDayIndex]) {
-						logsForEachDays[currentDayIndex].unshift(Chart.convertFlattenColumnsToObject(log));
+						logsForEachDays[currentDayIndex].unshift(Chart.convertFlattenColumnsToObject(log) as T);
 					} else {
-						logsForEachDays[currentDayIndex] = [Chart.convertFlattenColumnsToObject(log)];
+						logsForEachDays[currentDayIndex] = [Chart.convertFlattenColumnsToObject(log) as T];
 					}
 				} else {
 					// 隙間埋め
 					const latest = logs.find(l => isTimeBefore(new Date(l.date * 1000), current));
-					const data = latest ? Chart.convertFlattenColumnsToObject(latest as Record<string, any>) : null;
+					const data = latest ? Chart.convertFlattenColumnsToObject(latest) as T : null;
 					const newLog = this.getNewLog(data);
 					if (logsForEachDays[currentDayIndex]) {
 						logsForEachDays[currentDayIndex].unshift(newLog);
@@ -516,7 +515,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 
 			for (const logs of logsForEachDays) {
 				const log = this.aggregate(logs);
-				chart.unshift(Chart.countUniqueFields(log));
+				chart.unshift(Chart.countUniqueFields(log) as T);
 			}
 		}
 

From ffb9646ce9c3d2326a3e922e58702674eb65646c Mon Sep 17 00:00:00 2001
From: nullobsi <me@nullob.si>
Date: Thu, 27 May 2021 17:38:09 -0700
Subject: [PATCH 11/28] Add image description support (#7518)

* recieve image descriptions under the name property

* fix other components

* use comment for alt and title

* allow editing of file comment

* allow editing of file comment in note dialog

* federate note comments

* use file instead of this

* backend should accept comment on update

* update now actually accepts comment

* allow multiline descriptions

* image should also have description attached

* Update locales/ja-JP.yml

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>

* Use custom component with side-by-side image

* improve usability on mobile devices

* revert changes

* Update post-form-attaches.vue

* Update drive.file.vue

* Update media-caption.vue

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 locales/ja-JP.yml                             |   3 +
 src/client/components/drive.file.vue          |  24 ++
 src/client/components/image-viewer.vue        |   2 +-
 src/client/components/media-caption.vue       | 238 ++++++++++++++++++
 src/client/components/media-image.vue         |   4 +-
 src/client/components/post-form-attaches.vue  |  25 ++
 src/remote/activitypub/models/image.ts        |   2 +-
 src/remote/activitypub/renderer/document.ts   |   3 +-
 src/remote/activitypub/renderer/image.ts      |   3 +-
 .../api/endpoints/drive/files/update.ts       |  11 +
 src/services/drive/upload-from-url.ts         |   6 +
 11 files changed, 315 insertions(+), 6 deletions(-)
 create mode 100644 src/client/components/media-caption.vue

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e869f5b015..23f3bf7296 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -279,6 +279,7 @@ emptyDrive: "ドライブは空です"
 emptyFolder: "フォルダーは空です"
 unableToDelete: "削除できません"
 inputNewFileName: "新しいファイル名を入力してください"
+inputNewDescription: "新しいキャプションを入力してください"
 inputNewFolderName: "新しいフォルダ名を入力してください"
 circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
 hasChildFilesOrFolders: "このフォルダは空でないため、削除できません。"
@@ -546,6 +547,8 @@ disablePlayer: "プレイヤーを閉じる"
 expandTweet: "ツイートを展開する"
 themeEditor: "テーマエディター"
 description: "説明"
+describeFile: "キャプションを付ける"
+enterFileDescription: "キャプションを入力"
 author: "作者"
 leaveConfirm: "未保存の変更があります。破棄しますか?"
 manage: "管理"
diff --git a/src/client/components/drive.file.vue b/src/client/components/drive.file.vue
index 37b1afc1b3..3d20de23e9 100644
--- a/src/client/components/drive.file.vue
+++ b/src/client/components/drive.file.vue
@@ -87,6 +87,10 @@ export default defineComponent({
 				text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
 				icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash',
 				action: this.toggleSensitive
+			}, {
+				text: this.$ts.describeFile,
+				icon: 'fas fa-i-cursor',
+				action: this.describe
 			}, null, {
 				text: this.$ts.copyUrl,
 				icon: 'fas fa-link',
@@ -150,6 +154,26 @@ export default defineComponent({
 			});
 		},
 
+		describe() {
+			os.popup(import('@client/components/media-caption.vue'), {
+				title: this.$ts.describeFile,
+				input: {
+					placeholder: this.$ts.inputNewDescription,
+					default: this.file.comment !== null ? this.file.comment : '',
+				},
+				image: this.file
+			}, {
+				done: result => {
+					if (!result || result.canceled) return;
+					let comment = result.result;
+					os.api('drive/files/update', {
+						fileId: this.file.id,
+						comment: comment.length == 0 ? null : comment
+					});
+				}
+			}, 'closed');
+		},
+
 		toggleSensitive() {
 			os.api('drive/files/update', {
 				fileId: this.file.id,
diff --git a/src/client/components/image-viewer.vue b/src/client/components/image-viewer.vue
index ec22bd98ec..7701ae926f 100644
--- a/src/client/components/image-viewer.vue
+++ b/src/client/components/image-viewer.vue
@@ -2,7 +2,7 @@
 <MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
 	<div class="xubzgfga">
 		<header>{{ image.name }}</header>
-		<img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/>
+		<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
 		<footer>
 			<span>{{ image.type }}</span>
 			<span>{{ bytes(image.size) }}</span>
diff --git a/src/client/components/media-caption.vue b/src/client/components/media-caption.vue
new file mode 100644
index 0000000000..690927d4c5
--- /dev/null
+++ b/src/client/components/media-caption.vue
@@ -0,0 +1,238 @@
+<template>
+	<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
+		<div class="container">
+			<div class="fullwidth top-caption">
+				<div class="mk-dialog">
+					<header v-if="title"><Mfm :text="title"/></header>
+					<textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
+					<div class="buttons" v-if="(showOkButton || showCancelButton)">
+						<MkButton inline @click="ok" primary>{{ $ts.ok }}</MkButton>
+						<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton>
+					</div>
+				</div>
+			</div>
+			<div class="hdrwpsaf fullwidth">
+				<header>{{ image.name }}</header>
+				<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
+				<footer>
+					<span>{{ image.type }}</span>
+					<span>{{ bytes(image.size) }}</span>
+					<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
+				</footer>
+			</div>
+		</div>
+	</MkModal>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import MkModal from '@client/components/ui/modal.vue';
+import MkButton from '@client/components/ui/button.vue';
+import bytes from '@client/filters/bytes';
+import number from '@client/filters/number';
+
+export default defineComponent({
+	components: {
+		MkModal,
+		MkButton,
+	},
+
+	props: {
+		image: {
+			type: Object,
+			required: true,
+		},
+		title: {
+			type: String,
+			required: false
+		},
+		input: {
+			required: true
+		},
+		showOkButton: {
+			type: Boolean,
+			default: true
+		},
+		showCancelButton: {
+			type: Boolean,
+			default: true
+		},
+		cancelableByBgClick: {
+			type: Boolean,
+			default: true
+		},
+	},
+
+	emits: ['done', 'closed'],
+
+	data() {
+		return {
+			inputValue: this.input.default ? this.input.default : null
+		};
+	},
+
+	mounted() {
+		document.addEventListener('keydown', this.onKeydown);
+	},
+
+	beforeUnmount() {
+		document.removeEventListener('keydown', this.onKeydown);
+	},
+
+	methods: {
+		bytes,
+		number,
+
+		done(canceled, result?) {
+			this.$emit('done', { canceled, result });
+			this.$refs.modal.close();
+		},
+
+		async ok() {
+			if (!this.showOkButton) return;
+
+			const result = this.inputValue;
+			this.done(false, result);
+		},
+
+		cancel() {
+			this.done(true);
+		},
+
+		onBgClick() {
+			if (this.cancelableByBgClick) {
+				this.cancel();
+			}
+		},
+
+		onKeydown(e) {
+			if (e.which === 27) { // ESC
+				this.cancel();
+			}
+		},
+
+		onInputKeydown(e) {
+			if (e.which === 13) { // Enter
+				if (e.ctrlKey) {
+					e.preventDefault();
+					e.stopPropagation();
+					this.ok();
+				}
+			}
+		}
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.container {
+	display: flex;
+	width: 100%;
+	height: 100%;
+	flex-direction: row;
+}
+@media (max-width: 850px) {
+	.container {
+		flex-direction: column;
+	}
+	.top-caption {
+		padding-bottom: 8px;
+	}
+}
+.fullwidth {
+	width: 100%;
+	margin: auto;
+}
+.mk-dialog {
+	position: relative;
+	padding: 32px;
+	min-width: 320px;
+	max-width: 480px;
+	box-sizing: border-box;
+	text-align: center;
+	background: var(--panel);
+	border-radius: var(--radius);
+	margin: auto;
+
+	> header {
+		margin: 0 0 8px 0;
+		font-weight: bold;
+		font-size: 20px;
+	}
+
+	> .buttons {
+		margin-top: 16px;
+
+		> * {
+			margin: 0 8px;
+		}
+	}
+
+	> textarea {
+		display: block;
+		box-sizing: border-box;
+		padding: 0 24px;
+		margin: 0;
+		width: 100%;
+		font-size: 16px;
+		border: none;
+		border-radius: 0;
+		background: transparent;
+		color: var(--fg);
+		font-family: inherit;
+		max-width: 100%;
+		min-width: 100%;
+		min-height: 90px;
+
+		&:focus {
+			outline: none;
+		}
+
+		&:disabled {
+			opacity: 0.5;
+		}
+	}
+}
+.hdrwpsaf {
+	display: flex;
+	flex-direction: column;
+	height: 100%;
+
+	> header,
+	> footer {
+		align-self: center;
+		display: inline-block;
+		padding: 6px 9px;
+		font-size: 90%;
+		background: rgba(0, 0, 0, 0.5);
+		border-radius: 6px;
+		color: #fff;
+	}
+
+	> header {
+		margin-bottom: 8px;
+		opacity: 0.9;
+	}
+
+	> img {
+		display: block;
+		flex: 1;
+		min-height: 0;
+		object-fit: contain;
+		width: 100%;
+		cursor: zoom-out;
+		image-orientation: from-image;
+	}
+
+	> footer {
+		margin-top: 8px;
+		opacity: 0.8;
+
+		> span + span {
+			margin-left: 0.5em;
+			padding-left: 0.5em;
+			border-left: solid 1px rgba(255, 255, 255, 0.5);
+		}
+	}
+}
+</style>
diff --git a/src/client/components/media-image.vue b/src/client/components/media-image.vue
index 267e4debd2..863eb10272 100644
--- a/src/client/components/media-image.vue
+++ b/src/client/components/media-image.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="qjewsnkg" v-if="hide" @click="hide = false">
-	<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/>
+	<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
 	<div class="text">
 		<div>
 			<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
@@ -14,7 +14,7 @@
 		:title="image.name"
 		@click.prevent="onClick"
 	>
-		<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/>
+		<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
 		<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
 	</a>
 	<i class="fas fa-eye-slash" @click="hide = true"></i>
diff --git a/src/client/components/post-form-attaches.vue b/src/client/components/post-form-attaches.vue
index f832ea87b5..27e20fdfa8 100644
--- a/src/client/components/post-form-attaches.vue
+++ b/src/client/components/post-form-attaches.vue
@@ -89,6 +89,27 @@ export default defineComponent({
 				file.name = result;
 			});
 		},
+
+		async describe(file) {
+			os.popup(import("@client/components/media-caption.vue"), {
+				title: this.$ts.describeFile,
+				input: {
+					placeholder: this.$ts.inputNewDescription,
+					default: file.comment !== null ? file.comment : "",
+				},
+				image: file
+			}, {
+				done: result => {
+					if (!result || result.canceled) return;
+					let comment = result.result;
+					os.api('drive/files/update', {
+						fileId: file.id,
+						comment: comment.length == 0 ? null : comment
+					});
+				}
+			}, 'closed');
+		},
+
 		showFileMenu(file, ev: MouseEvent) {
 			if (this.menu) return;
 			this.menu = os.modalMenu([{
@@ -99,6 +120,10 @@ export default defineComponent({
 				text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
 				icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
 				action: () => { this.toggleSensitive(file) }
+			}, {
+				text: this.$ts.describeFile,
+				icon: 'fas fa-i-cursor',
+				action: () => { this.describe(file) }
 			}, {
 				text: this.$ts.attachCancel,
 				icon: 'fas fa-times-circle',
diff --git a/src/remote/activitypub/models/image.ts b/src/remote/activitypub/models/image.ts
index 79fc2bf4a6..7bec1d6030 100644
--- a/src/remote/activitypub/models/image.ts
+++ b/src/remote/activitypub/models/image.ts
@@ -28,7 +28,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<Drive
 	const instance = await fetchMeta();
 	const cache = instance.cacheRemoteFiles;
 
-	let file = await uploadFromUrl(image.url, actor, null, image.url, image.sensitive, false, !cache);
+	let file = await uploadFromUrl(image.url, actor, null, image.url, image.sensitive, false, !cache, image.name);
 
 	if (file.isLink) {
 		// URLが異なっている場合、同じ画像が以前に異なるURLで登録されていたということなので、
diff --git a/src/remote/activitypub/renderer/document.ts b/src/remote/activitypub/renderer/document.ts
index 4f6ea8c4ee..f6e9dca45d 100644
--- a/src/remote/activitypub/renderer/document.ts
+++ b/src/remote/activitypub/renderer/document.ts
@@ -4,5 +4,6 @@ import { DriveFiles } from '../../../models';
 export default (file: DriveFile) => ({
 	type: 'Document',
 	mediaType: file.type,
-	url: DriveFiles.getPublicUrl(file)
+	url: DriveFiles.getPublicUrl(file),
+	name: file.comment,
 });
diff --git a/src/remote/activitypub/renderer/image.ts b/src/remote/activitypub/renderer/image.ts
index ce98f98c62..cbd4fbbe68 100644
--- a/src/remote/activitypub/renderer/image.ts
+++ b/src/remote/activitypub/renderer/image.ts
@@ -4,5 +4,6 @@ import { DriveFiles } from '../../../models';
 export default (file: DriveFile) => ({
 	type: 'Image',
 	url: DriveFiles.getPublicUrl(file),
-	sensitive: file.isSensitive
+	sensitive: file.isSensitive,
+	name: file.comment
 });
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index 6eda83967b..f740fea67e 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -49,6 +49,14 @@ export const meta = {
 				'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか',
 				'en-US': 'Whether this media is NSFW'
 			}
+		},
+
+		comment: {
+			validator: $.optional.nullable.str,
+			default: undefined as any,
+			desc: {
+				'ja-JP': 'コメント'
+			}
 		}
 	},
 
@@ -92,6 +100,8 @@ export default define(meta, async (ps, user) => {
 
 	if (ps.name) file.name = ps.name;
 
+	if (ps.comment !== undefined) file.comment = ps.comment;
+
 	if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
 
 	if (ps.folderId !== undefined) {
@@ -113,6 +123,7 @@ export default define(meta, async (ps, user) => {
 
 	await DriveFiles.update(file.id, {
 		name: file.name,
+		comment: file.comment,
 		folderId: file.folderId,
 		isSensitive: file.isSensitive
 	});
diff --git a/src/services/drive/upload-from-url.ts b/src/services/drive/upload-from-url.ts
index 2f4c5aeeaf..2f660d9035 100644
--- a/src/services/drive/upload-from-url.ts
+++ b/src/services/drive/upload-from-url.ts
@@ -25,6 +25,12 @@ export default async (
 		name = null;
 	}
 
+	// If the comment is same as the name, skip comment
+	// (image.name is passed in when receiving attachment)
+	if (comment !== null && name == comment) {
+		comment = null;
+	}
+
 	// Create temp file
 	const [path, cleanup] = await createTemp();
 

From 857c88e8d63599f854f55510329083aab9021176 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 28 May 2021 22:52:30 +0900
Subject: [PATCH 12/28] fix type

---
 src/server/api/endpoints/i/notifications.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index b481fdba8f..c597a28ebb 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -103,9 +103,9 @@ export default define(meta, async (ps, user) => {
 		query.setParameters(followingQuery.getParameters());
 	}
 
-	if (ps.includeTypes?.length > 0) {
+	if (ps.includeTypes && ps.includeTypes.length > 0) {
 		query.andWhere(`notification.type IN (:...includeTypes)`, { includeTypes: ps.includeTypes });
-	} else if (ps.excludeTypes?.length > 0) {
+	} else if (ps.excludeTypes && ps.excludeTypes.length > 0) {
 		query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes });
 	}
 

From 30d2a1d8b654428e949c2584c3c29f41f00f6d2b Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 28 May 2021 22:52:38 +0900
Subject: [PATCH 13/28] fix bug

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

diff --git a/src/client/init.ts b/src/client/init.ts
index 19b95fc50e..12bb0d58c1 100644
--- a/src/client/init.ts
+++ b/src/client/init.ts
@@ -294,7 +294,7 @@ if ($i) {
 		}
 	}
 
-	const main = stream.useChannel('main', 'System');
+	const main = stream.useChannel('main', null, 'System');
 
 	// 自分の情報が更新されたとき
 	main.on('meUpdated', i => {

From 0eb115bf7e4324e5aabbe64785c2e45bc00ceb2c Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 28 May 2021 22:53:00 +0900
Subject: [PATCH 14/28] Resolve #7538

---
 src/server/api/endpoints/i/notifications.ts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index c597a28ebb..a10dc09df3 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -5,6 +5,7 @@ import define from '../../define';
 import { makePaginationQuery } from '../../common/make-pagination-query';
 import { Notifications, Followings, Mutings, Users } from '../../../../models';
 import { notificationTypes } from '../../../../types';
+import read from '@/services/note/read';
 
 export const meta = {
 	desc: {
@@ -116,5 +117,11 @@ export default define(meta, async (ps, user) => {
 		readNotification(user.id, notifications.map(x => x.id));
 	}
 
+	const notes = notifications.filter(notification => ['mention', 'reply', 'quote'].includes(notification.type)).map(notification => notification.note!);
+
+	if (notes.length > 0) {
+		read(user.id, notes);
+	}
+
 	return await Notifications.packMany(notifications, user.id);
 });

From d76345264ded05b2f8a1e7b75922914fd5aeb159 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 28 May 2021 22:57:04 +0900
Subject: [PATCH 15/28] fix bug

---
 src/client/ui/_common_/common.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/client/ui/_common_/common.vue b/src/client/ui/_common_/common.vue
index 1e825e0fe0..8da19a0984 100644
--- a/src/client/ui/_common_/common.vue
+++ b/src/client/ui/_common_/common.vue
@@ -43,7 +43,7 @@ export default defineComponent({
 		};
 
 		if ($i) {
-			const connection = stream.useChannel('main', 'UI');
+			const connection = stream.useChannel('main', null, 'UI');
 			connection.on('notification', onNotification);
 		}
 

From 24e7eeca0f912a11d4ec2664731b0f929ac26952 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 30 May 2021 10:05:12 +0900
Subject: [PATCH 16/28] fix local emoji detection

https://github.com/misskey-dev/misskey/pull/7526#discussion_r641886612
---
 src/misc/populate-emojis.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/misc/populate-emojis.ts b/src/misc/populate-emojis.ts
index a3f67ccb98..42aaaf0705 100644
--- a/src/misc/populate-emojis.ts
+++ b/src/misc/populate-emojis.ts
@@ -61,7 +61,7 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
 
 	if (emoji == null) return null;
 
-	const isLocal = emojiName.endsWith('@.');
+	const isLocal = emoji.host == null;
 	const url = isLocal ? emoji.url : `${config.url}/proxy/image.png?${query({url: emoji.url})}`;
 
 	return {

From 52e54cf0dc87fb9a4bf9ad0abbd8726ff92671d9 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 30 May 2021 10:05:25 +0900
Subject: [PATCH 17/28] refactor

---
 src/client/components/date-separated-list.vue | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/client/components/date-separated-list.vue b/src/client/components/date-separated-list.vue
index 34085cc070..6a0c7f29f2 100644
--- a/src/client/components/date-separated-list.vue
+++ b/src/client/components/date-separated-list.vue
@@ -1,11 +1,11 @@
 <script lang="ts">
-import { defineComponent, h, TransitionGroup } from 'vue';
+import { defineComponent, h, PropType, TransitionGroup } from 'vue';
 import MkAd from '@client/components/global/ad.vue';
 
 export default defineComponent({
 	props: {
 		items: {
-			type: Array,
+			type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>,
 			required: true,
 		},
 		direction: {

From 0263539202d16eb6a03484e0ead6d184be90de89 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Sun, 30 May 2021 13:48:23 +0900
Subject: [PATCH 18/28] Fix remote drive expire (#7543)

---
 src/models/repositories/drive-file.ts | 4 ++++
 src/services/drive/add-file.ts        | 3 ++-
 src/services/drive/delete-file.ts     | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts
index 590079fe4a..92bf12a4e0 100644
--- a/src/models/repositories/drive-file.ts
+++ b/src/models/repositories/drive-file.ts
@@ -59,6 +59,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 		const { sum } = await this
 			.createQueryBuilder('file')
 			.where('file.userId = :id', { id: id })
+			.andWhere('file.isLink = FALSE')
 			.select('SUM(file.size)', 'sum')
 			.getRawOne();
 
@@ -69,6 +70,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 		const { sum } = await this
 			.createQueryBuilder('file')
 			.where('file.userHost = :host', { host: toPuny(host) })
+			.andWhere('file.isLink = FALSE')
 			.select('SUM(file.size)', 'sum')
 			.getRawOne();
 
@@ -79,6 +81,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 		const { sum } = await this
 			.createQueryBuilder('file')
 			.where('file.userHost IS NULL')
+			.andWhere('file.isLink = FALSE')
 			.select('SUM(file.size)', 'sum')
 			.getRawOne();
 
@@ -89,6 +92,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 		const { sum } = await this
 			.createQueryBuilder('file')
 			.where('file.userHost IS NOT NULL')
+			.andWhere('file.isLink = FALSE')
 			.select('SUM(file.size)', 'sum')
 			.getRawOne();
 
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index ad9f753e79..2356a23cbe 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -267,7 +267,8 @@ async function upload(key: string, stream: fs.ReadStream | Buffer, type: string,
 
 async function deleteOldFile(user: IRemoteUser) {
 	const q = DriveFiles.createQueryBuilder('file')
-		.where('file.userId = :userId', { userId: user.id });
+		.where('file.userId = :userId', { userId: user.id })
+		.andWhere('file.isLink = FALSE');
 
 	if (user.avatarId) {
 		q.andWhere('file.id != :avatarId', { avatarId: user.avatarId });
diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts
index bb9c0ae2c3..2dd2445321 100644
--- a/src/services/drive/delete-file.ts
+++ b/src/services/drive/delete-file.ts
@@ -79,7 +79,7 @@ async function postProcess(file: DriveFile, isExpired = false) {
 			url: file.uri,
 			thumbnailUrl: null,
 			webpublicUrl: null,
-			size: 0,
+			storedInternal: false,
 			// ローカルプロキシ用
 			accessKey: uuid(),
 			thumbnailAccessKey: 'thumbnail-' + uuid(),

From 948b70cb0f5769cabc758c3c9c496af865b0cfef Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 30 May 2021 16:26:52 +0900
Subject: [PATCH 19/28] fix typo

Resolve #7540
---
 locales/ja-JP.yml                         |  4 ++--
 src/client/pages/settings/integration.vue | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 23f3bf7296..13f7e331ad 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -311,8 +311,8 @@ monthX: "{month}月"
 yearX: "{year}年"
 pages: "ページ"
 integration: "連携"
-connectSerice: "接続する"
-disconnectSerice: "切断する"
+connectService: "接続する"
+disconnectService: "切断する"
 enableLocalTimeline: "ローカルタイムラインを有効にする"
 enableGlobalTimeline: "グローバルタイムラインを有効にする"
 disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
diff --git a/src/client/pages/settings/integration.vue b/src/client/pages/settings/integration.vue
index 2d2be04051..f1c0a88afc 100644
--- a/src/client/pages/settings/integration.vue
+++ b/src/client/pages/settings/integration.vue
@@ -4,8 +4,8 @@
 		<div class="_formLabel"><i class="fab fa-twitter"></i> Twitter</div>
 		<div class="_formPanel" style="padding: 16px;">
 			<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
-			<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectSerice }}</MkButton>
-			<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectSerice }}</MkButton>
+			<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectService }}</MkButton>
+			<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectService }}</MkButton>
 		</div>
 	</div>
 
@@ -13,8 +13,8 @@
 		<div class="_formLabel"><i class="fab fa-discord"></i> Discord</div>
 		<div class="_formPanel" style="padding: 16px;">
 			<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
-			<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectSerice }}</MkButton>
-			<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectSerice }}</MkButton>
+			<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectService }}</MkButton>
+			<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectService }}</MkButton>
 		</div>
 	</div>
 
@@ -22,8 +22,8 @@
 		<div class="_formLabel"><i class="fab fa-github"></i> GitHub</div>
 		<div class="_formPanel" style="padding: 16px;">
 			<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
-			<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectSerice }}</MkButton>
-			<MkButton v-else @click="connectGithub" primary>{{ $ts.connectSerice }}</MkButton>
+			<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectService }}</MkButton>
+			<MkButton v-else @click="connectGithub" primary>{{ $ts.connectService }}</MkButton>
 		</div>
 	</div>
 </FormBase>

From 1077c2a63709994b27fba4760463251941501e8b Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 30 May 2021 16:42:22 +0900
Subject: [PATCH 20/28] :art:

---
 src/client/components/notifications.vue | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/client/components/notifications.vue b/src/client/components/notifications.vue
index 6caf8eb8e3..092c00f14e 100644
--- a/src/client/components/notifications.vue
+++ b/src/client/components/notifications.vue
@@ -12,10 +12,10 @@
 			<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
 		</XList>
 
-		<button class="_buttonPrimary" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
+		<MkButton primary style="margin: var(--margin) auto;" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
 			<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
 			<template v-if="moreFetching"><MkLoading inline/></template>
-		</button>
+		</MkButton>
 	</div>
 </transition>
 </template>
@@ -28,12 +28,14 @@ import XList from './date-separated-list.vue';
 import XNote from './note.vue';
 import { notificationTypes } from '../../types';
 import * as os from '@client/os';
+import MkButton from '@client/components/ui/button.vue';
 
 export default defineComponent({
 	components: {
 		XNotification,
 		XList,
 		XNote,
+		MkButton,
 	},
 
 	mixins: [

From 798aedfc0f15419c1f37298ce2242d240e0e11fe Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Sun, 30 May 2021 20:52:39 +0900
Subject: [PATCH 21/28] Supports Emoji 13.1 (#7539)

* Supports Emoji 13.1

* Fix regex
---
 COPYING                 | 4 ----
 package.json            | 2 ++
 src/emojilist.json      | 5 +++++
 src/misc/emoji-regex.ts | 5 ++---
 yarn.lock               | 8 ++++----
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/COPYING b/COPYING
index 5abc3e9895..13c13bf938 100644
--- a/COPYING
+++ b/COPYING
@@ -6,10 +6,6 @@ And is distributed under The GNU Affero General Public License Version 3, you sh
 
 Misskey includes several third-party Open-Source softwares.
 
-Unicode emoji regular expressions by Twitter, Inc.
-License: MIT
-https://github.com/twitter/twemoji-parser/blob/master/LICENSE.md
-
 Emoji keywords for Unicode 11 and below by Mu-An Chiou
 License: MIT
 https://github.com/muan/emojilib/blob/master/LICENSE
diff --git a/package.json b/package.json
index 610678989f..365fb865b9 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
 		"format": "gulp format"
 	},
 	"resolutions": {
+		"mfm-js/twemoji-parser": "13.1.x",
 		"chokidar": "^3.3.1",
 		"constantinople": "^4.0.1",
 		"jsonld/rdf-canonize/node-forge": "0.10.0",
@@ -233,6 +234,7 @@
 		"tsconfig-paths": "3.9.0",
 		"tslint": "6.1.3",
 		"tslint-sonarts": "1.9.0",
+		"twemoji-parser": "13.1.0",
 		"typeorm": "0.2.32",
 		"typescript": "4.2.4",
 		"ulid": "2.3.0",
diff --git a/src/emojilist.json b/src/emojilist.json
index 30cf6dd735..75c424ab4b 100644
--- a/src/emojilist.json
+++ b/src/emojilist.json
@@ -93,6 +93,9 @@
 	{ "category": "face", "char": "🥱", "name": "yawning", "keywords": ["face", "tired", "yawning"] },
 	{ "category": "face", "char": "😴", "name": "sleeping", "keywords": ["face", "tired", "sleepy", "night", "zzz"] },
 	{ "category": "face", "char": "💤", "name": "zzz", "keywords": ["sleepy", "tired", "dream"] },
+	{ "category": "face", "char": "\uD83D\uDE36\u200D\uD83C\uDF2B\uFE0F", "name": "face_in_clouds", "keywords": [] },
+	{ "category": "face", "char": "\uD83D\uDE2E\u200D\uD83D\uDCA8", "name": "face_exhaling", "keywords": [] },
+	{ "category": "face", "char": "\uD83D\uDE35\u200D\uD83D\uDCAB", "name": "face_with_spiral_eyes", "keywords": [] },
 	{ "category": "face", "char": "💩", "name": "poop", "keywords": ["hankey", "shitface", "fail", "turd", "shit"] },
 	{ "category": "face", "char": "😈", "name": "smiling_imp", "keywords": ["devil", "horns"] },
 	{ "category": "face", "char": "👿", "name": "imp", "keywords": ["devil", "angry", "horns"] },
@@ -1219,6 +1222,8 @@
 	{ "category": "symbols", "char": "💘", "name": "cupid", "keywords": ["love", "like", "heart", "affection", "valentines"] },
 	{ "category": "symbols", "char": "💝", "name": "gift_heart", "keywords": ["love", "valentines"] },
 	{ "category": "symbols", "char": "💟", "name": "heart_decoration", "keywords": ["purple-square", "love", "like"] },
+	{ "category": "symbols", "char": "\u2764\uFE0F\u200D\uD83D\uDD25", "name": "heart_on_fire", "keywords": [] },
+	{ "category": "symbols", "char": "\u2764\uFE0F\u200D\uD83E\uDE79", "name": "mending_heart", "keywords": [] },
 	{ "category": "symbols", "char": "☮", "name": "peace_symbol", "keywords": ["hippie"] },
 	{ "category": "symbols", "char": "✝", "name": "latin_cross", "keywords": ["christianity"] },
 	{ "category": "symbols", "char": "☪", "name": "star_and_crescent", "keywords": ["islam"] },
diff --git a/src/misc/emoji-regex.ts b/src/misc/emoji-regex.ts
index 9f9c360ff1..8b07fbd8f2 100644
--- a/src/misc/emoji-regex.ts
+++ b/src/misc/emoji-regex.ts
@@ -1,4 +1,3 @@
-// https://github.com/twitter/twemoji-parser/blob/master/src/lib/regex.js d1ea6ccfb72735698f4994e7015accc447eeac8e
-export const emojiRegex = /((?:\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d])|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udeeb\udeec\udef4-\udefc\udfe0-\udfeb]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd1d\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78\udd7a-\uddb4\uddb7\uddba\uddbc-\uddcb\uddd0\uddde-\uddff\ude70-\ude74\ude78-\ude7a\ude80-\ude86\ude90-\udea8\udeb0-\udeb6\udec0-\udec2\uded0-\uded6]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f)/;
+const twemojiRegex = require('twemoji-parser/dist/lib/regex').default;
 
-export const emojiRegexWithCustom = new RegExp(`(${emojiRegex.source}|:[0-9A-Za-z_]+:)`, 'g');
+export const emojiRegex = new RegExp(`(${twemojiRegex.source})`);
diff --git a/yarn.lock b/yarn.lock
index 9296aafc4e..b883eac0d3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10834,10 +10834,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
   integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
 
-twemoji-parser@13.0.x:
-  version "13.0.0"
-  resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-13.0.0.tgz#bd9d1b98474f1651dc174696b45cabefdfa405af"
-  integrity sha512-zMaGdskpH8yKjT2RSE/HwE340R4Fm+fbie4AaqjDa4H/l07YUmAvxkSfNl6awVWNRRQ0zdzLQ8SAJZuY5MgstQ==
+twemoji-parser@13.0.x, twemoji-parser@13.1.0, twemoji-parser@13.1.x:
+  version "13.1.0"
+  resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-13.1.0.tgz#65e7e449c59258791b22ac0b37077349127e3ea4"
+  integrity sha512-AQOzLJpYlpWMy8n+0ATyKKZzWlZBJN+G0C+5lhX7Ftc2PeEVdUU/7ns2Pn2vVje26AIZ/OHwFoUbdv6YYD/wGg==
 
 type-check@^0.4.0, type-check@~0.4.0:
   version "0.4.0"

From f1c4e4a10e26c3b4e136e0fd2cb77a243507be00 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 10:35:12 +0900
Subject: [PATCH 22/28] fix style

---
 src/client/ui/default.sidebar.vue | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/client/ui/default.sidebar.vue b/src/client/ui/default.sidebar.vue
index 725fd844d9..c7e2d30c7a 100644
--- a/src/client/ui/default.sidebar.vue
+++ b/src/client/ui/default.sidebar.vue
@@ -241,7 +241,6 @@ export default defineComponent({
 			> .text {
 				display: none;
 			}
-
 		}
 	}
 
@@ -309,7 +308,7 @@ export default defineComponent({
 		> .indicator {
 			position: absolute;
 			top: 0;
-			left: 20px;
+			left: 0;
 			color: var(--navIndicator);
 			font-size: 8px;
 			animation: blink 1s infinite;

From 79cb8364837326bd56d43504599bd5df07dc1758 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 11:05:34 +0900
Subject: [PATCH 23/28] Update deps

---
 gulpfile.ts  |   2 +-
 package.json |  58 +++---
 yarn.lock    | 559 +++++++++++++++++++++++++++++----------------------
 3 files changed, 349 insertions(+), 270 deletions(-)

diff --git a/gulpfile.ts b/gulpfile.ts
index 660dfb013e..2cdcbdb6fc 100644
--- a/gulpfile.ts
+++ b/gulpfile.ts
@@ -4,7 +4,7 @@
 
 import * as fs from 'fs';
 import * as gulp from 'gulp';
-import * as rimraf from 'rimraf';
+import rimraf from 'rimraf';
 const replace = require('gulp-replace');
 const terser = require('gulp-terser');
 const cssnano = require('gulp-cssnano');
diff --git a/package.json b/package.json
index 365fb865b9..ca33644052 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
 		"@koa/router": "9.0.1",
 		"@sentry/browser": "5.29.2",
 		"@sentry/tracing": "5.29.2",
-		"@sinonjs/fake-timers": "7.0.5",
+		"@sinonjs/fake-timers": "7.1.2",
 		"@syuilo/aiscript": "0.11.1",
 		"@types/bcryptjs": "2.4.2",
 		"@types/bull": "3.15.1",
@@ -59,23 +59,23 @@
 		"@types/jsdom": "16.2.10",
 		"@types/jsonld": "1.5.5",
 		"@types/katex": "0.11.0",
-		"@types/koa": "2.13.1",
+		"@types/koa": "2.13.3",
 		"@types/koa-bodyparser": "4.3.0",
 		"@types/koa-cors": "0.0.0",
 		"@types/koa-favicon": "2.0.19",
 		"@types/koa-logger": "3.1.1",
 		"@types/koa-mount": "4.0.0",
 		"@types/koa-send": "4.1.2",
-		"@types/koa-views": "2.0.4",
+		"@types/koa-views": "7.0.0",
 		"@types/koa__cors": "3.0.2",
 		"@types/koa__multer": "2.0.2",
 		"@types/koa__router": "8.0.4",
 		"@types/markdown-it": "12.0.1",
 		"@types/matter-js": "0.14.12",
 		"@types/mocha": "8.2.2",
-		"@types/node": "15.3.1",
+		"@types/node": "15.6.1",
 		"@types/node-fetch": "2.5.10",
-		"@types/nodemailer": "6.4.1",
+		"@types/nodemailer": "6.4.2",
 		"@types/nprogress": "0.2.0",
 		"@types/oauth": "0.9.1",
 		"@types/parse5": "6.0.0",
@@ -86,12 +86,12 @@
 		"@types/qrcode": "1.4.0",
 		"@types/random-seed": "0.3.3",
 		"@types/ratelimiter": "3.4.1",
-		"@types/redis": "2.8.28",
+		"@types/redis": "2.8.29",
 		"@types/rename": "1.0.3",
 		"@types/request-stats": "3.0.0",
 		"@types/rimraf": "3.0.0",
 		"@types/seedrandom": "2.4.28",
-		"@types/sharp": "0.28.1",
+		"@types/sharp": "0.28.2",
 		"@types/sinonjs__fake-timers": "6.0.2",
 		"@types/speakeasy": "2.0.5",
 		"@types/throttle-debounce": "2.1.0",
@@ -103,14 +103,14 @@
 		"@types/webpack-stream": "3.2.12",
 		"@types/websocket": "1.0.2",
 		"@types/ws": "7.4.4",
-		"@typescript-eslint/parser": "4.24.0",
+		"@typescript-eslint/parser": "4.25.0",
 		"@vue/compiler-sfc": "3.0.11",
 		"abort-controller": "3.0.0",
 		"apexcharts": "3.26.3",
 		"autobind-decorator": "2.4.0",
 		"autosize": "4.0.4",
 		"autwh": "0.1.0",
-		"aws-sdk": "2.910.0",
+		"aws-sdk": "2.918.0",
 		"bcryptjs": "2.4.3",
 		"blurhash": "1.1.3",
 		"broadcast-channel": "3.6.0",
@@ -121,20 +121,20 @@
 		"chart.js": "2.9.4",
 		"cli-highlight": "2.1.11",
 		"commander": "7.2.0",
-		"concurrently": "6.1.0",
+		"concurrently": "6.2.0",
 		"content-disposition": "0.5.3",
-		"core-js": "3.12.1",
+		"core-js": "3.13.1",
 		"crc-32": "1.2.0",
-		"css-loader": "5.2.4",
-		"cssnano": "5.0.3",
+		"css-loader": "5.2.6",
+		"cssnano": "5.0.5",
 		"dateformat": "4.5.1",
 		"diskusage": "1.1.3",
 		"escape-regexp": "0.0.1",
-		"eslint": "7.26.0",
-		"eslint-plugin-vue": "7.9.0",
+		"eslint": "7.27.0",
+		"eslint-plugin-vue": "7.10.0",
 		"eventemitter3": "4.0.7",
 		"feed": "4.2.2",
-		"file-type": "16.4.0",
+		"file-type": "16.5.0",
 		"fluent-ffmpeg": "2.1.2",
 		"glob": "7.1.7",
 		"got": "11.8.2",
@@ -149,12 +149,12 @@
 		"http-proxy-agent": "4.0.1",
 		"http-signature": "1.3.5",
 		"https-proxy-agent": "5.0.0",
-		"idb-keyval": "5.0.5",
+		"idb-keyval": "5.0.6",
 		"insert-text-at-cursor": "0.3.0",
 		"is-root": "2.1.0",
 		"is-svg": "4.3.1",
 		"js-yaml": "4.1.0",
-		"jsdom": "16.5.3",
+		"jsdom": "16.6.0",
 		"json5": "2.2.0",
 		"json5-loader": "4.0.1",
 		"jsonld": "4.0.1",
@@ -182,16 +182,16 @@
 		"multer": "1.4.2",
 		"nested-property": "4.0.0",
 		"node-fetch": "2.6.1",
-		"nodemailer": "6.6.0",
+		"nodemailer": "6.6.1",
 		"object-assign-deep": "0.4.0",
 		"os-utils": "0.0.14",
 		"parse5": "6.0.1",
 		"pg": "8.6.0",
 		"portscanner": "2.2.0",
-		"postcss": "8.2.15",
+		"postcss": "8.3.0",
 		"postcss-loader": "5.3.0",
 		"prismjs": "1.23.0",
-		"probe-image-size": "7.1.0",
+		"probe-image-size": "7.1.1",
 		"promise-limit": "2.7.0",
 		"promise-sequential": "1.1.1",
 		"pug": "3.0.2",
@@ -212,31 +212,31 @@
 		"rimraf": "3.0.2",
 		"rndstr": "1.0.0",
 		"s-age": "1.1.2",
-		"sass": "1.32.13",
+		"sass": "1.34.0",
 		"sass-loader": "11.1.1",
 		"seedrandom": "3.0.5",
-		"sharp": "0.28.2",
+		"sharp": "0.28.3",
 		"speakeasy": "2.0.0",
 		"stringz": "2.1.0",
 		"style-loader": "2.0.0",
 		"summaly": "2.4.0",
 		"syslog-pro": "1.0.0",
-		"systeminformation": "5.6.22",
+		"systeminformation": "5.7.4",
 		"syuilo-password-strength": "0.0.1",
 		"textarea-caret": "3.1.0",
 		"three": "0.117.1",
 		"throttle-debounce": "3.0.1",
 		"tinycolor2": "1.4.2",
 		"tmp": "0.2.1",
-		"ts-loader": "9.2.1",
-		"ts-node": "9.1.1",
+		"ts-loader": "9.2.2",
+		"ts-node": "10.0.0",
 		"tsc-alias": "1.2.11",
 		"tsconfig-paths": "3.9.0",
 		"tslint": "6.1.3",
 		"tslint-sonarts": "1.9.0",
 		"twemoji-parser": "13.1.0",
 		"typeorm": "0.2.32",
-		"typescript": "4.2.4",
+		"typescript": "4.3.2",
 		"ulid": "2.3.0",
 		"uuid": "8.3.2",
 		"v-debounce": "0.1.2",
@@ -251,10 +251,10 @@
 		"vue-svg-loader": "0.17.0-beta.2",
 		"vuedraggable": "4.0.1",
 		"web-push": "3.4.4",
-		"webpack": "5.37.1",
+		"webpack": "5.38.1",
 		"webpack-cli": "4.7.0",
 		"websocket": "1.0.34",
-		"ws": "7.4.5",
+		"ws": "7.4.6",
 		"xev": "2.0.1"
 	},
 	"devDependencies": {
diff --git a/yarn.lock b/yarn.lock
index b883eac0d3..2d9284c4cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -395,10 +395,10 @@
   dependencies:
     type-detect "4.0.8"
 
-"@sinonjs/fake-timers@7.0.5":
-  version "7.0.5"
-  resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz#558a7f8145a01366c44b3dcbdd7172c05c461564"
-  integrity sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==
+"@sinonjs/fake-timers@7.1.2":
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5"
+  integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==
   dependencies:
     "@sinonjs/commons" "^1.7.0"
 
@@ -440,6 +440,26 @@
   resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669"
   integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==
 
+"@tsconfig/node10@^1.0.7":
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.7.tgz#1eb1de36c73478a2479cc661ef5af1c16d86d606"
+  integrity sha512-aBvUmXLQbayM4w3A8TrjwrXs4DZ8iduJnuJLLRGdkWlyakCf1q6uHZJBzXoRA/huAEknG5tcUyQxN3A+In5euQ==
+
+"@tsconfig/node12@^1.0.7":
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.7.tgz#677bd9117e8164dc319987dd6ff5fc1ba6fbf18b"
+  integrity sha512-dgasobK/Y0wVMswcipr3k0HpevxFJLijN03A8mYfEPvWvOs14v0ZlYTR4kIgMx8g4+fTyTFv8/jLCIfRqLDJ4A==
+
+"@tsconfig/node14@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.0.tgz#5bd046e508b1ee90bc091766758838741fdefd6e"
+  integrity sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==
+
+"@tsconfig/node16@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1"
+  integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==
+
 "@types/accepts@*":
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575"
@@ -783,14 +803,14 @@
   dependencies:
     "@types/koa" "*"
 
-"@types/koa-views@2.0.4":
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/@types/koa-views/-/koa-views-2.0.4.tgz#3fa87ba13174f9816c6f7701fbf129dfe9855e39"
-  integrity sha512-aGFBVLiPC7FkXTqHLhnmjKhx3COV+GeJHO9OkLX/p/iAQTgDB5bbnsddx3XgrS6aACWyxR3BpQJVDdSqCNY1lw==
+"@types/koa-views@7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@types/koa-views/-/koa-views-7.0.0.tgz#5613450c77ab69c980c47104378da4b7669c5f2e"
+  integrity sha512-AB/NB+oFHcLOZJYFv3bG5Af8YbwYCD9/zK0WcKALsbjI/FRKrcXTUTC64RebDrkyOkBm3bpCgpGndhAH/3YQ2Q==
   dependencies:
-    "@types/koa" "*"
+    koa-views "*"
 
-"@types/koa@*", "@types/koa@2.13.1", "@types/koa@^2.13.1":
+"@types/koa@*", "@types/koa@^2.13.1":
   version "2.13.1"
   resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.1.tgz#e29877a6b5ad3744ab1024f6ec75b8cbf6ec45db"
   integrity sha512-Qbno7FWom9nNqu0yHZ6A0+RWt4mrYBhw3wpBAQ3+IuzGcLlfeYkzZrnMq5wsxulN2np8M4KKeUpTodsOsSad5Q==
@@ -804,6 +824,20 @@
     "@types/koa-compose" "*"
     "@types/node" "*"
 
+"@types/koa@2.13.3":
+  version "2.13.3"
+  resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.3.tgz#5b44c0956d7f7bf41f74ccfb530fec60fbed45ca"
+  integrity sha512-TaujBV+Dhe/FvmSMZJtCFBms+bqQacgUebk/M2C2tq8iGmHE/DDf4DcW2Hc7NqusVZmy5xzrWOjtdPKNP+fTfw==
+  dependencies:
+    "@types/accepts" "*"
+    "@types/content-disposition" "*"
+    "@types/cookies" "*"
+    "@types/http-assert" "*"
+    "@types/http-errors" "*"
+    "@types/keygrip" "*"
+    "@types/koa-compose" "*"
+    "@types/node" "*"
+
 "@types/koa__cors@3.0.2":
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-3.0.2.tgz#578917ffca964e98f5e9849996ae1eeda7c15704"
@@ -877,10 +911,10 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
   integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==
 
-"@types/node@15.3.1":
-  version "15.3.1"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-15.3.1.tgz#23a06b87eedb524016616e886b116b8fdcb180af"
-  integrity sha512-weaeiP4UF4XgF++3rpQhpIJWsCTS4QJw5gvBhQu6cFIxTwyxWIe3xbnrY/o2lTCQ0lsdb8YIUDUvLR4Vuz5rbw==
+"@types/node@15.6.1":
+  version "15.6.1"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-15.6.1.tgz#32d43390d5c62c5b6ec486a9bc9c59544de39a08"
+  integrity sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==
 
 "@types/node@^14.11.8":
   version "14.14.44"
@@ -892,10 +926,10 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.0.tgz#3ba770047723b3eeb8dc9fca02cce8a7fb6378da"
   integrity sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==
 
-"@types/nodemailer@6.4.1":
-  version "6.4.1"
-  resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.1.tgz#31f96f4410632f781d3613bd1f4293649e423f75"
-  integrity sha512-8081UY/0XTTDpuGqCnDc8IY+Q3DSg604wB3dBH0CaZlj4nZWHWuxtZ3NRZ9c9WUrz1Vfm6wioAUnqL3bsh49uQ==
+"@types/nodemailer@6.4.2":
+  version "6.4.2"
+  resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.2.tgz#d8ee254c969e6ad83fb9a0a0df3a817406a3fa3b"
+  integrity sha512-yhsqg5Xbr8aWdwjFS3QjkniW5/tLpWXtOYQcJdo9qE3DolBxsKzgRCQrteaMY0hos8MklJNSEsMqDpZynGzMNg==
   dependencies:
     "@types/node" "*"
 
@@ -991,10 +1025,10 @@
     "@types/node" "*"
     safe-buffer "*"
 
-"@types/redis@2.8.28":
-  version "2.8.28"
-  resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.28.tgz#5862b2b64aa7f7cbc76dafd7e6f06992b52c55e3"
-  integrity sha512-8l2gr2OQ969ypa7hFOeKqtFoY70XkHxISV0pAwmQ2nm6CSPb1brmTmqJCGGrekCo+pAZyWlNXr+Kvo6L/1wijA==
+"@types/redis@2.8.29":
+  version "2.8.29"
+  resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.29.tgz#f272dba985156e599e2523afb4f5f7e7586b56b5"
+  integrity sha512-/pjQ9lwnL/t1bEfRHQFEJB3kHCR65tpB19NEWmbqcgGgqrfeGo/9b4tUtHbClxQoy3+g6Esx2QRtV7fk7kBPYg==
   dependencies:
     "@types/node" "*"
 
@@ -1038,10 +1072,10 @@
     "@types/express-serve-static-core" "*"
     "@types/mime" "*"
 
-"@types/sharp@0.28.1":
-  version "0.28.1"
-  resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.28.1.tgz#dbd702bd6a8d42576b8faffe1c2ec06fdffaaaff"
-  integrity sha512-Jn9NHCjT3KXjxTpbtaxBI4iL+st5o9pWhMGVpHF+Cs+t/31lohLNXSW9PT9RSl7Ct7yBT2XFu7R/xfo0Y8HH2Q==
+"@types/sharp@0.28.2":
+  version "0.28.2"
+  resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.28.2.tgz#75bb9f60714ed752dc88c477ef55310f17c2f08f"
+  integrity sha512-xXanJalZA3EVSZ49667lBctyao75JiH5tD5/hKYu9u5C3d9rxEqOHvMOtx/oenJUqKKgIwIZEsL0hjmKo2rjJg==
   dependencies:
     "@types/node" "*"
 
@@ -1192,48 +1226,48 @@
   resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71"
   integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg==
 
-"@typescript-eslint/parser@4.24.0":
-  version "4.24.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.24.0.tgz#2e5f1cc78ffefe43bfac7e5659309a92b09a51bd"
-  integrity sha512-dj1ZIh/4QKeECLb2f/QjRwMmDArcwc2WorWPRlB8UNTZlY1KpTVsbX7e3ZZdphfRw29aTFUSNuGB8w9X5sS97w==
+"@typescript-eslint/parser@4.25.0":
+  version "4.25.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.25.0.tgz#6b2cb6285aa3d55bfb263c650739091b0f19aceb"
+  integrity sha512-OZFa1SKyEJpAhDx8FcbWyX+vLwh7OEtzoo2iQaeWwxucyfbi0mT4DijbOSsTgPKzGHr6GrF2V5p/CEpUH/VBxg==
   dependencies:
-    "@typescript-eslint/scope-manager" "4.24.0"
-    "@typescript-eslint/types" "4.24.0"
-    "@typescript-eslint/typescript-estree" "4.24.0"
+    "@typescript-eslint/scope-manager" "4.25.0"
+    "@typescript-eslint/types" "4.25.0"
+    "@typescript-eslint/typescript-estree" "4.25.0"
     debug "^4.1.1"
 
-"@typescript-eslint/scope-manager@4.24.0":
-  version "4.24.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.24.0.tgz#38088216f0eaf235fa30ed8cabf6948ec734f359"
-  integrity sha512-9+WYJGDnuC9VtYLqBhcSuM7du75fyCS/ypC8c5g7Sdw7pGL4NDTbeH38eJPfzIydCHZDoOgjloxSAA3+4l/zsA==
+"@typescript-eslint/scope-manager@4.25.0":
+  version "4.25.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.25.0.tgz#9d86a5bcc46ef40acd03d85ad4e908e5aab8d4ca"
+  integrity sha512-2NElKxMb/0rya+NJG1U71BuNnp1TBd1JgzYsldsdA83h/20Tvnf/HrwhiSlNmuq6Vqa0EzidsvkTArwoq+tH6w==
   dependencies:
-    "@typescript-eslint/types" "4.24.0"
-    "@typescript-eslint/visitor-keys" "4.24.0"
+    "@typescript-eslint/types" "4.25.0"
+    "@typescript-eslint/visitor-keys" "4.25.0"
 
-"@typescript-eslint/types@4.24.0":
-  version "4.24.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.24.0.tgz#6d0cca2048cbda4e265e0c4db9c2a62aaad8228c"
-  integrity sha512-tkZUBgDQKdvfs8L47LaqxojKDE+mIUmOzdz7r+u+U54l3GDkTpEbQ1Jp3cNqqAU9vMUCBA1fitsIhm7yN0vx9Q==
+"@typescript-eslint/types@4.25.0":
+  version "4.25.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.25.0.tgz#0e444a5c5e3c22d7ffa5e16e0e60510b3de5af87"
+  integrity sha512-+CNINNvl00OkW6wEsi32wU5MhHti2J25TJsJJqgQmJu3B3dYDBcmOxcE5w9cgoM13TrdE/5ND2HoEnBohasxRQ==
 
-"@typescript-eslint/typescript-estree@4.24.0":
-  version "4.24.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.24.0.tgz#b49249679a98014d8b03e8d4b70864b950e3c90f"
-  integrity sha512-kBDitL/by/HK7g8CYLT7aKpAwlR8doshfWz8d71j97n5kUa5caHWvY0RvEUEanL/EqBJoANev8Xc/mQ6LLwXGA==
+"@typescript-eslint/typescript-estree@4.25.0":
+  version "4.25.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.25.0.tgz#942e4e25888736bff5b360d9b0b61e013d0cfa25"
+  integrity sha512-1B8U07TGNAFMxZbSpF6jqiDs1cVGO0izVkf18Q/SPcUAc9LhHxzvSowXDTvkHMWUVuPpagupaW63gB6ahTXVlg==
   dependencies:
-    "@typescript-eslint/types" "4.24.0"
-    "@typescript-eslint/visitor-keys" "4.24.0"
+    "@typescript-eslint/types" "4.25.0"
+    "@typescript-eslint/visitor-keys" "4.25.0"
     debug "^4.1.1"
     globby "^11.0.1"
     is-glob "^4.0.1"
     semver "^7.3.2"
     tsutils "^3.17.1"
 
-"@typescript-eslint/visitor-keys@4.24.0":
-  version "4.24.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.24.0.tgz#a8fafdc76cad4e04a681a945fbbac4e35e98e297"
-  integrity sha512-4ox1sjmGHIxjEDBnMCtWFFhErXtKA1Ec0sBpuz0fqf3P+g3JFGyTxxbF06byw0FRsPnnbq44cKivH7Ks1/0s6g==
+"@typescript-eslint/visitor-keys@4.25.0":
+  version "4.25.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.25.0.tgz#863e7ed23da4287c5b469b13223255d0fde6aaa7"
+  integrity sha512-AmkqV9dDJVKP/TcZrbf6s6i1zYXt5Hl8qOLrRDTFfRNae4+LB8A4N3i+FLZPW85zIxRy39BgeWOfMS3HoH5ngg==
   dependencies:
-    "@typescript-eslint/types" "4.24.0"
+    "@typescript-eslint/types" "4.25.0"
     eslint-visitor-keys "^2.0.0"
 
 "@ungap/promise-all-settled@1.1.2":
@@ -1525,12 +1559,7 @@ acorn@^8.0.4:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
   integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
 
-acorn@^8.1.0:
-  version "8.1.1"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.1.tgz#fb0026885b9ac9f48bac1e185e4af472971149ff"
-  integrity sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==
-
-acorn@^8.2.1:
+acorn@^8.2.1, acorn@^8.2.4:
   version "8.2.4"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.4.tgz#caba24b08185c3b56e3168e97d15ed17f4d31fd0"
   integrity sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==
@@ -1574,6 +1603,16 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ajv@^8.0.1:
+  version "8.5.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.5.0.tgz#695528274bcb5afc865446aa275484049a18ae4b"
+  integrity sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    json-schema-traverse "^1.0.0"
+    require-from-string "^2.0.2"
+    uri-js "^4.2.2"
+
 alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
@@ -1928,10 +1967,10 @@ autwh@0.1.0:
   dependencies:
     oauth "0.9.15"
 
-aws-sdk@2.910.0:
-  version "2.910.0"
-  resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.910.0.tgz#7b5f448c6af2caae6c3c956eb56feea3d6dd9b1a"
-  integrity sha512-PC4x3qzxXxZEhd4CbcMdso/WnxeQvsiuYXHL+lb5B5d8zdORcXPaNmyIL/2DByyjJ2Ur4tfXgoQVPDKyYLcWEA==
+aws-sdk@2.918.0:
+  version "2.918.0"
+  resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.918.0.tgz#e4323de000262beb762e9c139f89e07282462f17"
+  integrity sha512-ZjWanOA1Zo664EyWLCnbUlkwCjoRPmSIMx529W4gk1418qo3oCEcvUy1HeibGGIClYnZZ7J4FMQvVDm2+JtHLQ==
   dependencies:
     buffer "4.9.2"
     events "1.1.1"
@@ -2182,6 +2221,17 @@ browserslist@^4.16.0:
     escalade "^3.1.1"
     node-releases "^1.1.71"
 
+browserslist@^4.16.6:
+  version "4.16.6"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
+  integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
+  dependencies:
+    caniuse-lite "^1.0.30001219"
+    colorette "^1.2.2"
+    electron-to-chromium "^1.3.723"
+    escalade "^3.1.1"
+    node-releases "^1.1.71"
+
 buffer-alloc-unsafe@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
@@ -2378,7 +2428,7 @@ camelcase@^5.0.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
-camelcase@^6.0.0, camelcase@^6.2.0:
+camelcase@^6.0.0:
   version "6.2.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
   integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
@@ -2423,6 +2473,11 @@ caniuse-lite@^1.0.30001208:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz#a999014a35cebd4f98c405930a057a0d75352eb9"
   integrity sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==
 
+caniuse-lite@^1.0.30001219:
+  version "1.0.30001230"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
+  integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==
+
 canonicalize@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.1.tgz#657b4f3fa38a6ecb97a9e5b7b26d7a19cc6e0da9"
@@ -2883,10 +2938,10 @@ color@^3.1.3:
     color-convert "^1.9.1"
     color-string "^1.5.4"
 
-colord@^1.7.0:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/colord/-/colord-1.7.2.tgz#474f0e46333cb5c7a191dbd571edeee19a5f97b6"
-  integrity sha512-/sQCxy6PEhZbrAn1+NVRRefy3k4jkWQGxk7mo2o0CoNA24jq4ujDc2jXzJ5uXphm/TwfdGOP0w8U+H+9ys4Peg==
+colord@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/colord/-/colord-2.0.1.tgz#1e7fb1f9fa1cf74f42c58cb9c20320bab8435aa0"
+  integrity sha512-vm5YpaWamD0Ov6TSG0GGmUIwstrWcfKQV/h2CmbR7PbNu41+qdB5PW9lpzhjedrpm08uuYvcXi0Oel1RLZIJuA==
 
 colorette@^1.2.0, colorette@^1.2.1, colorette@^1.2.2:
   version "1.2.2"
@@ -2975,10 +3030,10 @@ concat-stream@^1.5.2, concat-stream@^1.6.0:
     readable-stream "^2.2.2"
     typedarray "^0.0.6"
 
-concurrently@6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.1.0.tgz#00d22525d3fcdce7f34cc7f3c9753f90a57d6208"
-  integrity sha512-jy+xj49pvqeKjc2TAVXRIhrgPG51eBKDZti0kZ41kaWk9iLbyWBjH6KMFpW7peOLkEymD+ZM83Lx6UEy3N/M9g==
+concurrently@6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.2.0.tgz#587e2cb8afca7234172d8ea55176088632c4c56d"
+  integrity sha512-v9I4Y3wFoXCSY2L73yYgwA9ESrQMpRn80jMcqMgHx720Hecz2GZAvTI6bREVST6lkddNypDKRN22qhK0X8Y00g==
   dependencies:
     chalk "^4.1.0"
     date-fns "^2.16.1"
@@ -3088,10 +3143,10 @@ core-js-compat@^3.9.1:
     browserslist "^4.16.3"
     semver "7.0.0"
 
-core-js@3.12.1:
-  version "3.12.1"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112"
-  integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==
+core-js@3.13.1:
+  version "3.13.1"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.13.1.tgz#30303fabd53638892062d8b4e802cac7599e9fb7"
+  integrity sha512-JqveUc4igkqwStL2RTRn/EPFGBOfEZHxJl/8ej1mXJR75V3go2mFF4bmUYkEIT1rveHKnkUlcJX/c+f1TyIovQ==
 
 core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
@@ -3174,15 +3229,14 @@ css-declaration-sorter@^6.0.3:
   dependencies:
     timsort "^0.3.0"
 
-css-loader@5.2.4:
-  version "5.2.4"
-  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.4.tgz#e985dcbce339812cb6104ef3670f08f9893a1536"
-  integrity sha512-OFYGyINCKkdQsTrSYxzGSFnGS4gNjcXkKkQgWxK138jgnPt+lepxdjSZNc8sHAl5vP3DhsJUxufWIjOwI8PMMw==
+css-loader@5.2.6:
+  version "5.2.6"
+  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.6.tgz#c3c82ab77fea1f360e587d871a6811f4450cc8d1"
+  integrity sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==
   dependencies:
-    camelcase "^6.2.0"
     icss-utils "^5.1.0"
     loader-utils "^2.0.0"
-    postcss "^8.2.10"
+    postcss "^8.2.15"
     postcss-modules-extract-imports "^3.0.0"
     postcss-modules-local-by-default "^4.0.0"
     postcss-modules-scope "^3.0.0"
@@ -3271,22 +3325,22 @@ cssesc@^3.0.0:
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
   integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
 
-cssnano-preset-default@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.0.tgz#3ff4a1c102f72c7976580ce7f1c52325dc4628ed"
-  integrity sha512-VTO0WAlrEsU0u+A4RwALRs5zSVnD23WgYO8Np3HowBMZTqWIP1GvIWWzs9zZmjNgeL8U+70megRZymb+1yGg/w==
+cssnano-preset-default@^5.1.2:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.2.tgz#5d4877a91769823c5da6bcebd54996ecdf8aca12"
+  integrity sha512-spilp8LRw0sacuxiN9A/dyyPr6G/WISKMBKcBD4NMoPV0ENx4DeuWvIIrSx9PII2nJIDCO3kywkqTPreECBVOg==
   dependencies:
     css-declaration-sorter "^6.0.3"
     cssnano-utils "^2.0.1"
     postcss-calc "^8.0.0"
-    postcss-colormin "^5.1.0"
+    postcss-colormin "^5.2.0"
     postcss-convert-values "^5.0.1"
     postcss-discard-comments "^5.0.1"
     postcss-discard-duplicates "^5.0.1"
     postcss-discard-empty "^5.0.1"
     postcss-discard-overridden "^5.0.1"
     postcss-merge-longhand "^5.0.2"
-    postcss-merge-rules "^5.0.1"
+    postcss-merge-rules "^5.0.2"
     postcss-minify-font-values "^5.0.1"
     postcss-minify-gradients "^5.0.1"
     postcss-minify-params "^5.0.1"
@@ -3303,7 +3357,7 @@ cssnano-preset-default@^5.1.0:
     postcss-ordered-values "^5.0.1"
     postcss-reduce-initial "^5.0.1"
     postcss-reduce-transforms "^5.0.1"
-    postcss-svgo "^5.0.1"
+    postcss-svgo "^5.0.2"
     postcss-unique-selectors "^5.0.1"
 
 cssnano-utils@^2.0.1:
@@ -3311,13 +3365,13 @@ cssnano-utils@^2.0.1:
   resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2"
   integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==
 
-cssnano@5.0.3:
-  version "5.0.3"
-  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.3.tgz#3ae26411a176168e7a0ef425f4691579e1aed12a"
-  integrity sha512-Ga/a+IA6U0F9+MNmqrXgwn1A3btY5jFkla2iurL7i9PTmQmMu2Kc99W9a8KSxT8iLV0aoI+Q5Q9i3SpVAVNnrQ==
+cssnano@5.0.5:
+  version "5.0.5"
+  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.5.tgz#6b8787123bf4cd5a220a2fa6cb5bc036b0854b48"
+  integrity sha512-L2VtPXnq6rmcMC9vkBOP131sZu3ccRQI27ejKZdmQiPDpUlFkUbpXHgKN+cibeO1U4PItxVZp1zTIn5dHsXoyg==
   dependencies:
     cosmiconfig "^7.0.0"
-    cssnano-preset-default "^5.1.0"
+    cssnano-preset-default "^5.1.2"
     is-resolvable "^1.1.0"
 
 cssnano@^3.0.0:
@@ -3845,6 +3899,11 @@ electron-to-chromium@^1.3.712:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.717.tgz#78d4c857070755fb58ab64bcc173db1d51cbc25f"
   integrity sha512-OfzVPIqD1MkJ7fX+yTl2nKyOE4FReeVfMCzzxQS+Kp43hZYwHwThlGP+EGIZRXJsxCM7dqo8Y65NOX/HP12iXQ==
 
+electron-to-chromium@^1.3.723:
+  version "1.3.742"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz#7223215acbbd3a5284962ebcb6df85d88b95f200"
+  integrity sha512-ihL14knI9FikJmH2XUIDdZFWJxvr14rPSdOhJ7PpS27xbz8qmaRwCwyg/bmFwjWKmWK9QyamiCZVCvXm5CH//Q==
+
 emoji-regex@^7.0.1:
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -4031,7 +4090,7 @@ escape-regexp@0.0.1:
   resolved "https://registry.yarnpkg.com/escape-regexp/-/escape-regexp-0.0.1.tgz#f44bda12d45bbdf9cb7f862ee7e4827b3dd32254"
   integrity sha1-9EvaEtRbvfnLf4Yu5+SCez3TIlQ=
 
-escape-string-regexp@4.0.0:
+escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
   integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
@@ -4053,17 +4112,17 @@ escodegen@^2.0.0:
   optionalDependencies:
     source-map "~0.6.1"
 
-eslint-plugin-vue@7.9.0:
-  version "7.9.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.9.0.tgz#f8e83a2a908f4c43fc8304f5401d4ff671f3d560"
-  integrity sha512-2Q0qQp5+5h+pZvJKCbG1/jCRUYrdgAz5BYKGyTlp2NU8mx09u3Hp7PsH6d5qef6ojuPoCXMnrbbDxeoplihrSw==
+eslint-plugin-vue@7.10.0:
+  version "7.10.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.10.0.tgz#251749aa99e089e085275f011042c6e74189f89a"
+  integrity sha512-xdr6e4t/L2moRAeEQ9HKgge/hFq+w9v5Dj+BA54nTAzSFdUyKLiSOdZaRQjCHMY0Pk2WaQBFH9QiWG60xiC+6A==
   dependencies:
     eslint-utils "^2.1.0"
     natural-compare "^1.4.0"
     semver "^7.3.2"
     vue-eslint-parser "^7.6.0"
 
-eslint-scope@^5.0.0, eslint-scope@^5.1.1:
+eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
   integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
@@ -4088,10 +4147,10 @@ eslint-visitor-keys@^2.0.0:
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
   integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
 
-eslint@7.26.0:
-  version "7.26.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.26.0.tgz#d416fdcdcb3236cd8f282065312813f8c13982f6"
-  integrity sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==
+eslint@7.27.0:
+  version "7.27.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.27.0.tgz#665a1506d8f95655c9274d84bd78f7166b07e9c7"
+  integrity sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA==
   dependencies:
     "@babel/code-frame" "7.12.11"
     "@eslint/eslintrc" "^0.4.1"
@@ -4101,12 +4160,14 @@ eslint@7.26.0:
     debug "^4.0.1"
     doctrine "^3.0.0"
     enquirer "^2.3.5"
+    escape-string-regexp "^4.0.0"
     eslint-scope "^5.1.1"
     eslint-utils "^2.1.0"
     eslint-visitor-keys "^2.0.0"
     espree "^7.3.1"
     esquery "^1.4.0"
     esutils "^2.0.2"
+    fast-deep-equal "^3.1.3"
     file-entry-cache "^6.0.1"
     functional-red-black-tree "^1.0.1"
     glob-parent "^5.0.0"
@@ -4118,7 +4179,7 @@ eslint@7.26.0:
     js-yaml "^3.13.1"
     json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.4.1"
-    lodash "^4.17.21"
+    lodash.merge "^4.6.2"
     minimatch "^3.0.4"
     natural-compare "^1.4.0"
     optionator "^0.9.1"
@@ -4127,7 +4188,7 @@ eslint@7.26.0:
     semver "^7.2.1"
     strip-ansi "^6.0.0"
     strip-json-comments "^3.1.0"
-    table "^6.0.4"
+    table "^6.0.9"
     text-table "^0.2.0"
     v8-compile-cache "^2.0.3"
 
@@ -4342,6 +4403,11 @@ fast-deep-equal@^3.1.1:
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
   integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
 
+fast-deep-equal@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
 fast-glob@^3.1.1:
   version "3.2.4"
   resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3"
@@ -4400,15 +4466,14 @@ file-entry-cache@^6.0.1:
   dependencies:
     flat-cache "^3.0.4"
 
-file-type@16.4.0:
-  version "16.4.0"
-  resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.4.0.tgz#464197e44bd94a452d77b09085d977ae0dad2df4"
-  integrity sha512-MDAkwha3wHg11Lp++2T3Gu347eC/DB4r7nYj6iZaf1l7UhGBh2746QKxg0BWC8w2dJsxUEmH8KvLueX+GthN2w==
+file-type@16.5.0:
+  version "16.5.0"
+  resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.0.tgz#16a2626f3b33bac612f6e81e52216f3a7c8e12a2"
+  integrity sha512-OxgWA9tbL8N/WP00GD1z8O0MiwQKFyWRs1q+3FhjdvcGgKqwxcejyGWso3n4/IMU6DdwV+ARZ4A7TTnPkDcSiw==
   dependencies:
     readable-web-to-node-stream "^3.0.0"
     strtok3 "^6.0.3"
     token-types "^2.0.0"
-    typedarray-to-buffer "^3.1.5"
 
 fill-range@^4.0.0:
   version "4.0.0"
@@ -5345,10 +5410,10 @@ icss-utils@^5.0.0, icss-utils@^5.1.0:
   resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
   integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
 
-idb-keyval@5.0.5:
-  version "5.0.5"
-  resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-5.0.5.tgz#1b02984dcf42ad4aa290bf9f10935b485419df34"
-  integrity sha512-cqi65rrjhgPExI9vmSU7VcYEbHCUfIBY+9YUWxyr0PyGizptFgGFnvZQ0w+tqOXk1lUcGCZGVLfabf7QnR2S0g==
+idb-keyval@5.0.6:
+  version "5.0.6"
+  resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-5.0.6.tgz#62fe4a6703fb5ec86661f41330c94fda65e6d0e6"
+  integrity sha512-6lJuVbwyo82mKSH6Wq2eHkt9LcbwHAelMIcMe0tP4p20Pod7tTxq9zf0ge2n/YDfMOpDryerfmmYyuQiaFaKOg==
 
 ieee754@1.1.13, ieee754@^1.1.13, ieee754@^1.1.4:
   version "1.1.13"
@@ -5736,10 +5801,10 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
-is-potential-custom-element-name@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
-  integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
+is-potential-custom-element-name@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+  integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
 
 is-promise@^2.0.0:
   version "2.2.2"
@@ -5981,13 +6046,13 @@ jschardet@^2.1.0:
   resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184"
   integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q==
 
-jsdom@16.5.3:
-  version "16.5.3"
-  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.3.tgz#13a755b3950eb938b4482c407238ddf16f0d2136"
-  integrity sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==
+jsdom@16.6.0:
+  version "16.6.0"
+  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.6.0.tgz#f79b3786682065492a3da6a60a4695da983805ac"
+  integrity sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==
   dependencies:
     abab "^2.0.5"
-    acorn "^8.1.0"
+    acorn "^8.2.4"
     acorn-globals "^6.0.0"
     cssom "^0.4.4"
     cssstyle "^2.3.0"
@@ -5995,12 +6060,13 @@ jsdom@16.5.3:
     decimal.js "^10.2.1"
     domexception "^2.0.1"
     escodegen "^2.0.0"
+    form-data "^3.0.0"
     html-encoding-sniffer "^2.0.1"
-    is-potential-custom-element-name "^1.0.0"
+    http-proxy-agent "^4.0.1"
+    https-proxy-agent "^5.0.0"
+    is-potential-custom-element-name "^1.0.1"
     nwsapi "^2.2.0"
     parse5 "6.0.1"
-    request "^2.88.2"
-    request-promise-native "^1.0.9"
     saxes "^5.0.1"
     symbol-tree "^3.2.4"
     tough-cookie "^4.0.0"
@@ -6010,7 +6076,7 @@ jsdom@16.5.3:
     whatwg-encoding "^1.0.5"
     whatwg-mimetype "^2.3.0"
     whatwg-url "^8.5.0"
-    ws "^7.4.4"
+    ws "^7.4.5"
     xml-name-validator "^3.0.0"
 
 jsesc@^2.5.1:
@@ -6038,6 +6104,11 @@ json-schema-traverse@^0.4.1:
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
   integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
 
+json-schema-traverse@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+  integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
 json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -6277,7 +6348,7 @@ koa-slow@2.1.0:
     lodash.isregexp "3.0.5"
     q "1.4.1"
 
-koa-views@7.0.1:
+koa-views@*, koa-views@7.0.1:
   version "7.0.1"
   resolved "https://registry.yarnpkg.com/koa-views/-/koa-views-7.0.1.tgz#0c8f8e65d5cd2e08249430cb83dc361e49a17a5a"
   integrity sha512-yS8751DXHXXDbdl/oUZd0PsgnxR0MLiguu77Eqrgu6yawE9Hi99wNKiVENb0Kfgsmvq/8px7YCI+USgxaTB1LA==
@@ -6504,6 +6575,11 @@ lodash.camelcase@^4.3.0:
   resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
   integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
 
+lodash.clonedeep@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+  integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
 lodash.debounce@^4.0.8:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -6589,6 +6665,11 @@ lodash.throttle@^4.0.0:
   resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
   integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
 
+lodash.truncate@^4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+  integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
+
 lodash.uniq@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -7127,11 +7208,6 @@ nanoid@3.1.20, nanoid@^3.1.20:
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
   integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
 
-nanoid@^3.1.22:
-  version "3.1.22"
-  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
-  integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==
-
 nanoid@^3.1.23:
   version "3.1.23"
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
@@ -7217,10 +7293,10 @@ node-abi@^2.21.0:
   dependencies:
     semver "^5.4.1"
 
-node-addon-api@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239"
-  integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
+node-addon-api@^3.2.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
+  integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
 
 node-fetch@2.6.1, node-fetch@^2.6.1:
   version "2.6.1"
@@ -7263,10 +7339,10 @@ node-releases@^1.1.70, node-releases@^1.1.71:
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
   integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
 
-nodemailer@6.6.0:
-  version "6.6.0"
-  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.0.tgz#ed47bb572b48d9d0dca3913fdc156203f438f427"
-  integrity sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg==
+nodemailer@6.6.1:
+  version "6.6.1"
+  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.1.tgz#2a05fbf205b897d71bf43884167b5d4d3bd01b99"
+  integrity sha512-1xzFN3gqv+/qJ6YRyxBxfTYstLNt0FCtZaFRvf4Sg9wxNGWbwFmGXVpfSi6ThGK6aRxAo+KjHtYSW8NvCsNSAg==
 
 nofilter@^2.0.3:
   version "2.0.3"
@@ -8045,13 +8121,14 @@ postcss-colormin@^2.1.8:
     postcss "^5.0.13"
     postcss-value-parser "^3.2.3"
 
-postcss-colormin@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.1.0.tgz#686da694e5e638eac141364e150eb936b3a8e79f"
-  integrity sha512-5s+VNfQ5CsR6yvBc6Tc8NK9cxb/c8sA547zy+8ofL04gs/GygmOcVZt2s6jJn7TvntAw0Bp6MDpq4bd51EPwdw==
+postcss-colormin@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.0.tgz#2b620b88c0ff19683f3349f4cf9e24ebdafb2c88"
+  integrity sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==
   dependencies:
-    browserslist "^4.16.0"
-    colord "^1.7.0"
+    browserslist "^4.16.6"
+    caniuse-api "^3.0.0"
+    colord "^2.0.1"
     postcss-value-parser "^4.1.0"
 
 postcss-convert-values@^2.3.4:
@@ -8177,12 +8254,12 @@ postcss-merge-rules@^2.0.3:
     postcss-selector-parser "^2.2.2"
     vendors "^1.0.0"
 
-postcss-merge-rules@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.1.tgz#4ff61c5089d86845184a0f149e88d687028bef7e"
-  integrity sha512-UR6R5Ph0c96QB9TMBH3ml8/kvPCThPHepdhRqAbvMRDRHQACPC8iM5NpfIC03+VRMZTGXy4L/BvFzcDFCgb+fA==
+postcss-merge-rules@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz#d6e4d65018badbdb7dcc789c4f39b941305d410a"
+  integrity sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==
   dependencies:
-    browserslist "^4.16.0"
+    browserslist "^4.16.6"
     caniuse-api "^3.0.0"
     cssnano-utils "^2.0.1"
     postcss-selector-parser "^6.0.5"
@@ -8484,10 +8561,10 @@ postcss-svgo@^2.1.1:
     postcss-value-parser "^3.2.3"
     svgo "^0.7.0"
 
-postcss-svgo@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.1.tgz#6ed5e01e164e59204978994d844c653a331a8100"
-  integrity sha512-cD7DFo6tF9i5eWvwtI4irKOHCpmASFS0xvZ5EQIgEdA1AWfM/XiHHY/iss0gcKHhkqwgYmuo2M0KhJLd5Us6mg==
+postcss-svgo@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.2.tgz#bc73c4ea4c5a80fbd4b45e29042c34ceffb9257f"
+  integrity sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==
   dependencies:
     postcss-value-parser "^4.1.0"
     svgo "^2.3.0"
@@ -8529,14 +8606,14 @@ postcss-zindex@^2.0.1:
     postcss "^5.0.4"
     uniqs "^2.0.0"
 
-postcss@8.2.15:
-  version "8.2.15"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65"
-  integrity sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==
+postcss@8.3.0, postcss@^8.2.15:
+  version "8.3.0"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.0.tgz#b1a713f6172ca427e3f05ef1303de8b65683325f"
+  integrity sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==
   dependencies:
     colorette "^1.2.2"
     nanoid "^3.1.23"
-    source-map "^0.6.1"
+    source-map-js "^0.6.2"
 
 postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16:
   version "5.2.18"
@@ -8557,15 +8634,6 @@ postcss@^8.1.10:
     nanoid "^3.1.20"
     source-map "^0.6.1"
 
-postcss@^8.2.10:
-  version "8.2.12"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.12.tgz#81248a1a87e0f575cc594a99a08207fd1c4addc4"
-  integrity sha512-BJnGT5+0q2tzvs6oQfnY2NpEJ7rIXNfBnZtQOKCIsweeWXBXeDd5k31UgTdS3d/c02ouspufn37mTaHWkJyzMQ==
-  dependencies:
-    colorette "^1.2.2"
-    nanoid "^3.1.22"
-    source-map "^0.6.1"
-
 postgres-array@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
@@ -8657,10 +8725,10 @@ prismjs@1.23.0:
   optionalDependencies:
     clipboard "^2.0.0"
 
-probe-image-size@7.1.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.1.0.tgz#2b0f8474c9c0c68f3b640e353fe64127585f0f6b"
-  integrity sha512-T7F4ZF4iWQJWhj/ijPyh88fHen9UtaUwtV+QMZ1NkmpUSDHmfYlZgRUTOcFKnqi95I6kpGBQ+3pF1dCtVmDeIg==
+probe-image-size@7.1.1:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.1.1.tgz#ea3dc7acd69fb041212de12bb390be58c1025917"
+  integrity sha512-lvpHKqtino5SSrFEKxFncco8raLywljcLbjcE35VIRl5O+u1qLXenNaEfnopYdJgN4PPvvBxdr8b7sEUTvfY/w==
   dependencies:
     lodash.merge "^4.6.2"
     needle "^2.5.2"
@@ -9232,13 +9300,6 @@ request-promise-core@1.1.2:
   dependencies:
     lodash "^4.17.11"
 
-request-promise-core@1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
-  integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
-  dependencies:
-    lodash "^4.17.19"
-
 request-promise-native@1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59"
@@ -9248,15 +9309,6 @@ request-promise-native@1.0.7:
     stealthy-require "^1.1.1"
     tough-cookie "^2.3.3"
 
-request-promise-native@^1.0.9:
-  version "1.0.9"
-  resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
-  integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
-  dependencies:
-    request-promise-core "1.1.4"
-    stealthy-require "^1.1.1"
-    tough-cookie "^2.3.3"
-
 request-stats@3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/request-stats/-/request-stats-3.0.0.tgz#769155dc8974d78d4a1cb87bbf14eaab985afe25"
@@ -9291,7 +9343,7 @@ request@2.88.0:
     tunnel-agent "^0.6.0"
     uuid "^3.3.2"
 
-request@^2.88.0, request@^2.88.2:
+request@^2.88.0:
   version "2.88.2"
   resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
   integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -9332,6 +9384,11 @@ require-directory@^2.1.1:
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
 
+require-from-string@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+  integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
 require-main-filename@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
@@ -9524,10 +9581,10 @@ sass-loader@11.1.1:
     klona "^2.0.4"
     neo-async "^2.6.2"
 
-sass@1.32.13:
-  version "1.32.13"
-  resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.13.tgz#8d29c849e625a415bce71609c7cf95e15f74ed00"
-  integrity sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==
+sass@1.34.0:
+  version "1.34.0"
+  resolved "https://registry.yarnpkg.com/sass/-/sass-1.34.0.tgz#e46d5932d8b0ecc4feb846d861f26a578f7f7172"
+  integrity sha512-rHEN0BscqjUYuomUEaqq3BMgsXqQfkcMVR7UhscsAVub0/spUrZGBMxQXFS2kfiDsPLZw5yuU9iJEFNC2x38Qw==
   dependencies:
     chokidar ">=3.0.0 <4.0.0"
 
@@ -9665,14 +9722,14 @@ shallow-clone@^3.0.0:
   dependencies:
     kind-of "^6.0.2"
 
-sharp@0.28.2:
-  version "0.28.2"
-  resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.28.2.tgz#31c6ebdf8ddb9b4ca3e30179e3f4a73f0c7474e4"
-  integrity sha512-CdmySbsQVe/+ZM2j9zzvUfWumM0L0iHj1kpxJMFuyWvSuBULebvGCdOLb1f5vbbBrIGroX714Fx1wiWaKniz4A==
+sharp@0.28.3:
+  version "0.28.3"
+  resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.28.3.tgz#ecd74cefd020bee4891bb137c9850ee2ce277a8b"
+  integrity sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==
   dependencies:
     color "^3.1.3"
     detect-libc "^1.0.3"
-    node-addon-api "^3.1.0"
+    node-addon-api "^3.2.0"
     prebuild-install "^6.1.2"
     semver "^7.3.5"
     simple-get "^3.1.0"
@@ -9824,6 +9881,11 @@ source-list-map@^2.0.0, source-list-map@^2.0.1:
   resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
   integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
 
+source-map-js@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
+  integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
+
 source-map-resolve@^0.5.0:
   version "0.5.3"
   resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -10371,25 +10433,27 @@ syslog-pro@1.0.0:
   dependencies:
     moment "^2.22.2"
 
-systeminformation@5.6.22:
-  version "5.6.22"
-  resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.6.22.tgz#7751340e2835bd3d0b28694ae273e168b235f1df"
-  integrity sha512-GJYkEUn2rKKsRG8ieUhnOXkowSTno2s8CD/jkeyi3KErxSq0HCYu+7YYbxirL3/bh7zE3yjy/S52rEnrBjjf7Q==
+systeminformation@5.7.4:
+  version "5.7.4"
+  resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.7.4.tgz#13fcc29bd3836cf5043802f0f2532d0c4961a4ea"
+  integrity sha512-m6oziAu2zP8IMnNZpVWptzpcaXG6x59c2sQB8BI7DTcfBOTLXj5jGgjWxCVP65c5k7Fwhn35yVTCIZEypc1n9A==
 
 syuilo-password-strength@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/syuilo-password-strength/-/syuilo-password-strength-0.0.1.tgz#08f71a8f0ecb77db649f3d9a6424510d9d945f52"
   integrity sha1-CPcajw7Ld9tknz2aZCRRDZ2UX1I=
 
-table@^6.0.4:
-  version "6.0.4"
-  resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d"
-  integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw==
+table@^6.0.9:
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
+  integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
   dependencies:
-    ajv "^6.12.4"
-    lodash "^4.17.20"
+    ajv "^8.0.1"
+    lodash.clonedeep "^4.5.0"
+    lodash.truncate "^4.4.2"
     slice-ansi "^4.0.0"
     string-width "^4.2.0"
+    strip-ansi "^6.0.0"
 
 tapable@^1.0.0-beta.5:
   version "1.1.3"
@@ -10712,21 +10776,25 @@ tree-kill@^1.2.2:
   resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
   integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
 
-ts-loader@9.2.1:
-  version "9.2.1"
-  resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.1.tgz#5699af8d10aa3a763aadfced1d4b275a432b76eb"
-  integrity sha512-BLfLa4paMQyf819haKxxbZqA1aLDqsk8XEZLmd7E1eBa0NsEHYFcTWlUlPmYMGhvD/IMi0NcIW3A/G7vzr3oiA==
+ts-loader@9.2.2:
+  version "9.2.2"
+  resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.2.tgz#416333900621c82d5eb1b1f6dea4114111f096bf"
+  integrity sha512-hNIhGTQHtNKjOzR2ZtQ2OSVbXPykOae+zostf1IlHCf61Mt41GMJurKNqrYUbzHgpmj6UWRu8eBfb7q0XliV0g==
   dependencies:
     chalk "^4.1.0"
     enhanced-resolve "^5.0.0"
     micromatch "^4.0.0"
     semver "^7.3.4"
 
-ts-node@9.1.1:
-  version "9.1.1"
-  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
-  integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
+ts-node@10.0.0:
+  version "10.0.0"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be"
+  integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==
   dependencies:
+    "@tsconfig/node10" "^1.0.7"
+    "@tsconfig/node12" "^1.0.7"
+    "@tsconfig/node14" "^1.0.0"
+    "@tsconfig/node16" "^1.0.1"
     arg "^4.1.0"
     create-require "^1.1.0"
     diff "^4.0.1"
@@ -10931,10 +10999,10 @@ typeorm@0.2.32:
     yargs "^16.2.0"
     zen-observable-ts "^1.0.0"
 
-typescript@4.2.4:
-  version "4.2.4"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
-  integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
+typescript@4.3.2:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
+  integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
 
 uc.micro@^1.0.1, uc.micro@^1.0.5:
   version "1.0.6"
@@ -11348,6 +11416,14 @@ watchpack@^2.0.0:
     glob-to-regexp "^0.4.1"
     graceful-fs "^4.1.2"
 
+watchpack@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce"
+  integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==
+  dependencies:
+    glob-to-regexp "^0.4.1"
+    graceful-fs "^4.1.2"
+
 web-push@3.4.4:
   version "3.4.4"
   resolved "https://registry.yarnpkg.com/web-push/-/web-push-3.4.4.tgz#b11523ada0f4b8c2481f65d1d059acd45ba27ca0"
@@ -11413,10 +11489,18 @@ webpack-sources@^2.1.1:
     source-list-map "^2.0.1"
     source-map "^0.6.1"
 
-webpack@5.37.1:
-  version "5.37.1"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.37.1.tgz#2deb5acd350583c1ab9338471f323381b0b0c14b"
-  integrity sha512-btZjGy/hSjCAAVHw+cKG+L0M+rstlyxbO2C+BOTaQ5/XAnxkDrP5sVbqWhXgo4pL3X2dcOib6rqCP20Zr9PLow==
+webpack-sources@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.0.tgz#9ed2de69b25143a4c18847586ad9eccb19278cfa"
+  integrity sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==
+  dependencies:
+    source-list-map "^2.0.1"
+    source-map "^0.6.1"
+
+webpack@5.38.1:
+  version "5.38.1"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.38.1.tgz#5224c7f24c18e729268d3e3bc97240d6e880258e"
+  integrity sha512-OqRmYD1OJbHZph6RUMD93GcCZy4Z4wC0ele4FXyYF0J6AxO1vOSuIlU1hkS/lDlR9CDYBz64MZRmdbdnFFoT2g==
   dependencies:
     "@types/eslint-scope" "^3.7.0"
     "@types/estree" "^0.0.47"
@@ -11428,7 +11512,7 @@ webpack@5.37.1:
     chrome-trace-event "^1.0.2"
     enhanced-resolve "^5.8.0"
     es-module-lexer "^0.4.0"
-    eslint-scope "^5.1.1"
+    eslint-scope "5.1.1"
     events "^3.2.0"
     glob-to-regexp "^0.4.1"
     graceful-fs "^4.2.4"
@@ -11439,8 +11523,8 @@ webpack@5.37.1:
     schema-utils "^3.0.0"
     tapable "^2.1.1"
     terser-webpack-plugin "^5.1.1"
-    watchpack "^2.0.0"
-    webpack-sources "^2.1.1"
+    watchpack "^2.2.0"
+    webpack-sources "^2.3.0"
 
 webpack@^5:
   version "5.33.2"
@@ -11626,15 +11710,10 @@ write-json-file@^2.3.0:
     sort-keys "^2.0.0"
     write-file-atomic "^2.0.0"
 
-ws@7.4.5:
-  version "7.4.5"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1"
-  integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==
-
-ws@^7.4.4:
-  version "7.4.4"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
-  integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
+ws@7.4.6, ws@^7.4.5:
+  version "7.4.6"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
+  integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
 
 xev@2.0.1:
   version "2.0.1"

From bb926dd30122de8b9901c0cd81f3872496f495b7 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 11:05:37 +0900
Subject: [PATCH 24/28] fix bug

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

diff --git a/src/client/os.ts b/src/client/os.ts
index e6355b45b8..987844b2d2 100644
--- a/src/client/os.ts
+++ b/src/client/os.ts
@@ -60,7 +60,7 @@ export const api = ((endpoint: string, data: Record<string, any> = {}, token?: s
 			if (res.status === 200) {
 				resolve(body);
 				if (debug) {
-					log!.res = markRaw(body);
+					log!.res = markRaw(JSON.parse(JSON.stringify(body)));
 					log!.state = 'success';
 				}
 			} else if (res.status === 204) {

From dc44d9a0a8a8f71b2edf41f8fa3bd36009fb51ae Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 12:02:02 +0900
Subject: [PATCH 25/28] fix

---
 src/client/pages/instance/overview.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/client/pages/instance/overview.vue b/src/client/pages/instance/overview.vue
index dca2529e1b..cb9cff9fc5 100644
--- a/src/client/pages/instance/overview.vue
+++ b/src/client/pages/instance/overview.vue
@@ -92,6 +92,7 @@ export default defineComponent({
 			version,
 			url,
 			stats: null,
+			meta: null,
 			fetchStats: () => os.api('stats', {}),
 			fetchServerInfo: () => os.api('admin/server-info', {}),
 			fetchJobs: () => os.api('admin/queue/deliver-delayed', {}),

From b608f63a1a530508079318da2252f246fe3dcd9f Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 12:02:13 +0900
Subject: [PATCH 26/28] New Crowdin updates (#7527)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Korean)
---
 locales/ar-SA.yml |  2 --
 locales/cs-CZ.yml |  2 --
 locales/de-DE.yml |  7 +++++--
 locales/en-US.yml |  7 +++++--
 locales/es-ES.yml |  2 --
 locales/fr-FR.yml |  2 --
 locales/id-ID.yml | 14 ++++++--------
 locales/it-IT.yml |  2 --
 locales/ja-KS.yml |  2 --
 locales/ko-KR.yml |  7 +++++--
 locales/pl-PL.yml |  7 +++++--
 locales/ru-RU.yml |  2 --
 locales/uk-UA.yml |  2 --
 locales/zh-CN.yml |  7 +++++--
 locales/zh-TW.yml | 14 +++++++-------
 15 files changed, 38 insertions(+), 41 deletions(-)

diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml
index 631027cb7a..9c20ea7524 100644
--- a/locales/ar-SA.yml
+++ b/locales/ar-SA.yml
@@ -259,8 +259,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "الصفحات"
 integration: "دمج"
-connectSerice: "أوصل"
-disconnectSerice: "قطع الاتصال"
 enableLocalTimeline: "تفعيل الخيط المحلي"
 enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
 disablingTimelinesInfo: "سيتمكن المسؤولون ومن تعديل دائمًا و من الوصول إلى جميع المخططات الزمنية ، حتى إذا لم يتم تمكينها."
diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml
index 6d62b5345e..995d8eccd8 100644
--- a/locales/cs-CZ.yml
+++ b/locales/cs-CZ.yml
@@ -269,8 +269,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Stránky"
 integration: "Integrace"
-connectSerice: "Připojit"
-disconnectSerice: "Odpojit"
 enableLocalTimeline: "Povolit lokální čas"
 enableGlobalTimeline: "Povolit globální čas"
 registration: "Registrace"
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index 1f35b9de72..e3edcf5f40 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -279,6 +279,7 @@ emptyDrive: "Drive ist leer"
 emptyFolder: "Der Ordner ist leer"
 unableToDelete: "Nicht löschbar"
 inputNewFileName: "Gib einen neuen Dateinamen ein"
+inputNewDescription: "Gib eine neue Beschreibung ein"
 inputNewFolderName: "Gib einen neuen Ordnernamen ein"
 circularReferenceFolder: "Der Zielordner ist ein Unterorder des Ordners, den du verschieben möchtest."
 hasChildFilesOrFolders: "Dieser Ordner kann nicht gelöscht werden, da er nicht leer ist."
@@ -310,8 +311,8 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Seiten"
 integration: "Integration"
-connectSerice: "Verbinden"
-disconnectSerice: "Trennen"
+connectService: "Verbinden"
+disconnectService: "Trennen"
 enableLocalTimeline: "Lokale Chronik aktivieren"
 enableGlobalTimeline: "Globale Chronik aktivieren"
 disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
@@ -546,6 +547,8 @@ disablePlayer: "Video-Player schließen"
 expandTweet: "Tweet ausklappen"
 themeEditor: "Farbthemen-Editor"
 description: "Beschreibung"
+describeFile: "Beschreibung hinzufügen"
+enterFileDescription: "Beschreibung eingeben"
 author: "Autor"
 leaveConfirm: "Es gibt unspeicherte Änderungen. Möchtest du diese verwerfen?"
 manage: "Verwaltung"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 4cf417d21b..3dd581c8a4 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -279,6 +279,7 @@ emptyDrive: "The drive is empty"
 emptyFolder: "This folder is empty"
 unableToDelete: "Unable to delete"
 inputNewFileName: "Enter a new filename"
+inputNewDescription: "Enter new caption"
 inputNewFolderName: "Enter a new folder name"
 circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
 hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
@@ -310,8 +311,8 @@ monthX: "{month}"
 yearX: "{year} /"
 pages: "Pages"
 integration: "Integration"
-connectSerice: "Connect"
-disconnectSerice: "Disconnect"
+connectService: "Connect"
+disconnectService: "Disconnect"
 enableLocalTimeline: "Enable local timeline"
 enableGlobalTimeline: "Enable global timeline"
 disablingTimelinesInfo: "Admins and Mods will always have access to all timelines, even if they are not enabled."
@@ -546,6 +547,8 @@ disablePlayer: "Close video player"
 expandTweet: "Expand tweet"
 themeEditor: "Theme editor"
 description: "Description"
+describeFile: "Add caption"
+enterFileDescription: "Enter caption"
 author: "Author"
 leaveConfirm: "There are unsaved changes. Do you want to discard them?"
 manage: "Management"
diff --git a/locales/es-ES.yml b/locales/es-ES.yml
index ae7fba8976..89e170678d 100644
--- a/locales/es-ES.yml
+++ b/locales/es-ES.yml
@@ -309,8 +309,6 @@ monthX: "Mes {month}"
 yearX: "Año {year}"
 pages: "Páginas"
 integration: "Integración"
-connectSerice: "Conectarse"
-disconnectSerice: "Desconectarse"
 enableLocalTimeline: "Habilitar linea de tiempo local"
 enableGlobalTimeline: "Habilitar linea de tiempo global"
 disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia el administrador y los moderadores pueden seguir usándolos"
diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index c62b1c3b6e..174a3a8f5a 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -310,8 +310,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Pages"
 integration: "Intégrations"
-connectSerice: "Connecter"
-disconnectSerice: "Déconnecter"
 enableLocalTimeline: "Activer le fil local"
 enableGlobalTimeline: "Activer le fil global"
 disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s et les modérateur·rice·s pourront toujours y accéder."
diff --git a/locales/id-ID.yml b/locales/id-ID.yml
index 5f401bc4b1..ed1ac14121 100644
--- a/locales/id-ID.yml
+++ b/locales/id-ID.yml
@@ -1,5 +1,5 @@
 ---
-_lang_: "Bahasa Jepang"
+_lang_: "Bahasa Indonesia"
 headlineMisskey: "Jaringan terhubung melalui note"
 introMisskey: "Selamat datang! Misskey adalah perangkat mikroblog tercatu bersifat sumber terbuka.\nMulailah menuliskan catatan, bagikan peristiwa terkini, serta ceritakan segala tentangmu.📡\nTunjukkan juga reaksimu pada catatan pengguna lain.👍\nMari jelajahi dunia baru🚀"
 monthAndDay: "{day} {month}"
@@ -310,8 +310,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Halaman"
 integration: "Integrasi"
-connectSerice: "Sambungkan"
-disconnectSerice: "Putuskan"
 enableLocalTimeline: "Nyalakan linimasa lokal"
 enableGlobalTimeline: "Nyalakan linimasa global"
 disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua linimasa meskipun linimasa tersebut tidak diaktifkan."
@@ -977,9 +975,9 @@ _theme:
     infoFg: "Teks informasi"
     infoWarnBg: "Latar belakang peringatan"
     infoWarnFg: "Teks peringatan"
-    cwBg: "Latar belakang tombol CW"
-    cwFg: "Teks tombol CW"
-    cwHoverBg: "Latar belakang tombol CW (Mengambang)"
+    cwBg: "Latar belakang tombol Sembunyikan Konten"
+    cwFg: "Teks tombol Sembunyikan Konten"
+    cwHoverBg: "Latar belakang tombol Sembunyikan Konten (Mengambang)"
     toastBg: "Latar belakang pemberitahuan"
     toastFg: "Teks pemberitahuan"
     buttonBg: "Latar belakang tombol"
@@ -1122,7 +1120,7 @@ _widgets:
   aiscript: "Konsol AiScript"
 _cw:
   hide: "Sembunyikan"
-  show: "Selebihnya"
+  show: "Lihat konten"
   chars: "{count} karakter"
   files: "{count} berkas"
 _poll:
@@ -1551,7 +1549,7 @@ _pages:
       fn: "Fungsi"
       _fn:
         slots: "Slot"
-        slots-info: "Pisahkan setiap slow dengan baris baru"
+        slots-info: "Pisahkan setiap slot dengan baris baru"
         arg1: "Keluaran"
       for: "Ulangi"
       _for:
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index 69c8152d7f..0fdf78c799 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -305,8 +305,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Pagine"
 integration: "App collegate"
-connectSerice: "Connetti"
-disconnectSerice: "Disconnetti"
 enableLocalTimeline: "Abilita Timeline locale"
 enableGlobalTimeline: "Abilita Timeline federata"
 disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e i moderatori potranno sempre accederci."
diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml
index 6435b5835b..060c7b142d 100644
--- a/locales/ja-KS.yml
+++ b/locales/ja-KS.yml
@@ -308,8 +308,6 @@ monthX: "{month}月"
 yearX: "{year}年"
 pages: "ページ"
 integration: "連携"
-connectSerice: "つなぐ"
-disconnectSerice: "切ってまう"
 enableLocalTimeline: "ローカルタイムラインを使えるようにする"
 enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
 disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index 49069d258f..3d313b8c7c 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -279,6 +279,7 @@ emptyDrive: "드라이브가 비어 있습니다"
 emptyFolder: "폴더가 비어 있습니다"
 unableToDelete: "삭제할 수 없습니다"
 inputNewFileName: "바꿀 파일명을 입력해 주세요"
+inputNewDescription: "새 캡션을 입력해 주세요"
 inputNewFolderName: "바꿀 폴더명을 입력해 주세요"
 circularReferenceFolder: "지정한 폴더가 이동할 폴더의 하위 폴더입니다."
 hasChildFilesOrFolders: "이 폴더는 비어있지 않기 때문에 삭제할 수 없습니다."
@@ -310,8 +311,8 @@ monthX: "{month}월"
 yearX: "{year}년"
 pages: "페이지"
 integration: "연동"
-connectSerice: "접속"
-disconnectSerice: "연결 끊기"
+connectService: "계정 연동"
+disconnectService: "계정 연동 해제"
 enableLocalTimeline: "로컬 타임라인 활성화"
 enableGlobalTimeline: "글로벌 타임라인 활성화"
 disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
@@ -546,6 +547,8 @@ disablePlayer: "플레이어 닫기"
 expandTweet: "트윗 확장하기"
 themeEditor: "테마 에디터"
 description: "설명"
+describeFile: "캡션 추가"
+enterFileDescription: "캡션 입력"
 author: "작성자"
 leaveConfirm: "저장하지 않은 변경사항이 있습니다. 취소하시겠습니까?"
 manage: "관리"
diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml
index 4b4c80f7f3..550bda78b0 100644
--- a/locales/pl-PL.yml
+++ b/locales/pl-PL.yml
@@ -135,6 +135,7 @@ settingGuide: "Proponowana konfiguracja"
 cacheRemoteFiles: "Przechowuj zdalne pliki w pamięci podręcznej"
 cacheRemoteFilesDescription: "Gdy ta opcja jest wyłączona, zdalne pliki są ładowane bezpośrednio ze zdalnych instancji. Wyłączenie the opcji zmniejszy użycie powierzchni dyskowej, ale zwiększy transfer, ponieważ miniaturki nie będą generowane."
 flagAsBot: "To konto jest botem"
+flagAsBotDescription: "Jeżeli ten kanał jest kontrolowany przez jakiś program, ustaw tę opcję. Jeżeli włączona, będzie działać jako flaga informująca innych programistów, aby zapobiegać nieskończonej interakcji z różnymi botami i dostosowywać wewnętrzne systemy Misskey, traktując konto jako bota."
 flagAsCat: "To konto jest kotem"
 flagAsCatDescription: "Przełącz tę opcję, aby konto było oznaczone jako kot."
 autoAcceptFollowed: "Automatycznie przyjmuj prośby o możliwość obserwacji od użytkowników, których obserwujesz"
@@ -182,6 +183,7 @@ clearQueueConfirmTitle: "Czy na pewno chcesz wyczyścić kolejkę?"
 clearCachedFiles: "Wyczyść pamięć podręczną"
 clearCachedFilesConfirm: "Czy na pewno chcesz usunąć wszystkie zdalne pliki z pamięci podręcznej?"
 blockedInstances: "Zablokowane instancje"
+blockedInstancesDescription: "Wypisz nazwy hostów instancji, które powinny zostać zablokowane. Wypisane instancje nie będą mogły dłużej komunikować się z tą instancją."
 muteAndBlock: "Wycisz / Zablokuj"
 mutedUsers: "Wyciszeni użytkownicy"
 blockedUsers: "Zablokowani użytkownicy"
@@ -274,6 +276,7 @@ emptyDrive: "Dysk jest pusty"
 emptyFolder: "Ten katalog jest pusty"
 unableToDelete: "Nie można usunąć"
 inputNewFileName: "Wprowadź nową nazwę pliku"
+inputNewDescription: "Proszę wpisać nowy napis"
 inputNewFolderName: "Wprowadź nową nazwę katalogu"
 circularReferenceFolder: "Katalog docelowy jest podkatalogiem katalogu, który chcesz przenieść."
 hasChildFilesOrFolders: "Ponieważ ten katalog nie jest pusty, nie może być usunięty."
@@ -305,8 +308,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Strony"
 integration: "Integracja"
-connectSerice: "Połącz"
-disconnectSerice: "Rozłącz"
 enableLocalTimeline: "Włącz lokalną oś czasu"
 enableGlobalTimeline: "Włącz globalną oś czasu"
 disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone."
@@ -532,6 +533,8 @@ disablePlayer: "Zamknij odtwarzacz wideo"
 expandTweet: "Rozwiń tweet"
 themeEditor: "Edytor motywu"
 description: "Opis"
+describeFile: "dodaj podpis"
+enterFileDescription: "Wprowadź napis"
 author: "Autor"
 leaveConfirm: "Są niezapisane zmiany. Czy chcesz je odrzucić?"
 manage: "Zarządzanie"
diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml
index 2610403a71..c9700f4c91 100644
--- a/locales/ru-RU.yml
+++ b/locales/ru-RU.yml
@@ -309,8 +309,6 @@ monthX: "{month} месяц"
 yearX: "{year} год"
 pages: "Страницы"
 integration: "Интеграция"
-connectSerice: "Соединение"
-disconnectSerice: "Отключение"
 enableLocalTimeline: "Включить локальную ленту"
 enableGlobalTimeline: "Включить глобальную ленту"
 disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам, даже если они отключены."
diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml
index bb010ed5f6..3b8e6461c4 100644
--- a/locales/uk-UA.yml
+++ b/locales/uk-UA.yml
@@ -307,8 +307,6 @@ monthX: "{month}"
 yearX: "{year}"
 pages: "Сторінки"
 integration: "Інтеграція"
-connectSerice: "Під’єднати"
-disconnectSerice: "Відключитися"
 enableLocalTimeline: "Увімкнути локальну стрічку"
 enableGlobalTimeline: "Увімкнути глобальну стрічку"
 disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 4754fec4a4..905c84575c 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -279,6 +279,7 @@ emptyDrive: "驱动器为空"
 emptyFolder: "空文件夹"
 unableToDelete: "无法删除"
 inputNewFileName: "请输入新文件名"
+inputNewDescription: "请输入新标题"
 inputNewFolderName: "请输入新文件名"
 circularReferenceFolder: "目标文件夹是您要移动的文件夹的子文件夹。"
 hasChildFilesOrFolders: "此文件夹不为空,无法删除。"
@@ -310,8 +311,8 @@ monthX: "{month}月"
 yearX: "{year}年"
 pages: "页面"
 integration: "关联"
-connectSerice: "连接"
-disconnectSerice: "断开连接"
+connectService: "连接"
+disconnectService: "断开连接"
 enableLocalTimeline: "启用本地时间线功能"
 enableGlobalTimeline: "启用全局时间线"
 disablingTimelinesInfo: "即使时间线功能被禁用,出于便利性的原因,管理员和数据图表也可以继续使用。"
@@ -546,6 +547,8 @@ disablePlayer: "关闭播放器"
 expandTweet: "展开贴文"
 themeEditor: "主题编辑器"
 description: "描述"
+describeFile: "添加标题"
+enterFileDescription: "输入标题"
 author: "作者"
 leaveConfirm: "存在未保存的更改。要放弃更改吗?"
 manage: "管理"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index e8c7e55531..dd9552a871 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -1,18 +1,19 @@
 ---
 _lang_: "繁體中文"
-headlineMisskey: "貼文連繫網絡"
-introMisskey: "歡迎! Misskey是一個開源且去中心化的社群網絡。\n通過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
+headlineMisskey: "貼文連繫網路"
+introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網路。\n透過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
 monthAndDay: "{month}月 {day}日"
 search: "搜尋"
 notifications: "通知"
 username: "使用者名稱"
 password: "密碼"
+forgotPassword: "忘記密碼"
 fetchingAsApObject: "從聯邦宇宙取得中..."
 ok: "OK"
 gotIt: "知道了"
 cancel: "取消"
 enterUsername: "輸入使用者名稱"
-renotedBy: "{user} 轉發了"
+renotedBy: "{user} 轉傳了"
 noNotes: "貼文不可用。"
 noNotifications: "沒有通知"
 instance: "實例"
@@ -92,9 +93,9 @@ followRequestPending: "追隨許可批准中"
 enterEmoji: "輸入表情符號"
 renote: "轉發"
 unrenote: "取消轉發"
-renoted: "轉發成功"
+renoted: "轉傳成功"
 cantRenote: "無法轉發此貼文。"
-cantReRenote: "無法轉發之前已經轉發過的內容。"
+cantReRenote: "無法轉傳之前已經轉傳過的內容。"
 quote: "引用"
 pinnedNote: "已置頂的貼文"
 pinned: "置頂"
@@ -309,8 +310,6 @@ monthX: "{month}月"
 yearX: "{year}年"
 pages: "頁面"
 integration: "整合"
-connectSerice: "連線"
-disconnectSerice: "中斷連線"
 enableLocalTimeline: "開啟本地時間軸"
 enableGlobalTimeline: "啟用公開時間軸"
 disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
@@ -733,6 +732,7 @@ noBotProtectionWarning: "尚未設定Bot防護。"
 configure: "設定"
 expiration: "期限"
 middle: "中"
+emailNotConfiguredWarning: "沒有設定電子郵件地址"
 _ad:
   back: "返回"
 _gallery:

From caf40e40fbd444c050d8d3cc60f4dd2898950900 Mon Sep 17 00:00:00 2001
From: MeiMei <30769358+mei23@users.noreply.github.com>
Date: Mon, 31 May 2021 13:04:13 +0900
Subject: [PATCH 27/28] Supports Array ActivityStreams type  (#7536)

* Supports Array type

* Fix

* Fix Service to Note

* Update type.ts

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 src/remote/activitypub/kernel/accept/index.ts | 14 ++---
 src/remote/activitypub/kernel/create/index.ts |  6 +-
 src/remote/activitypub/kernel/reject/index.ts | 14 ++---
 .../activitypub/kernel/undo/announce.ts       |  5 +-
 src/remote/activitypub/kernel/undo/index.ts   | 26 +++-----
 src/remote/activitypub/kernel/update/index.ts |  8 +--
 src/remote/activitypub/models/note.ts         |  6 +-
 src/remote/activitypub/models/person.ts       |  8 +--
 src/remote/activitypub/type.ts                | 61 ++++++++++++-------
 src/server/api/endpoints/ap/show.ts           | 10 +--
 10 files changed, 76 insertions(+), 82 deletions(-)

diff --git a/src/remote/activitypub/kernel/accept/index.ts b/src/remote/activitypub/kernel/accept/index.ts
index 083e312a6f..79cdbb2ef7 100644
--- a/src/remote/activitypub/kernel/accept/index.ts
+++ b/src/remote/activitypub/kernel/accept/index.ts
@@ -1,12 +1,12 @@
 import Resolver from '../../resolver';
 import { IRemoteUser } from '../../../../models/entities/user';
 import acceptFollow from './follow';
-import { IAccept, IFollow } from '../../type';
+import { IAccept, isFollow, getApType } from '../../type';
 import { apLogger } from '../../logger';
 
 const logger = apLogger;
 
-export default async (actor: IRemoteUser, activity: IAccept): Promise<void> => {
+export default async (actor: IRemoteUser, activity: IAccept): Promise<string> => {
 	const uri = activity.id || activity;
 
 	logger.info(`Accept: ${uri}`);
@@ -18,13 +18,7 @@ export default async (actor: IRemoteUser, activity: IAccept): Promise<void> => {
 		throw e;
 	});
 
-	switch (object.type) {
-	case 'Follow':
-		acceptFollow(actor, object as IFollow);
-		break;
+	if (isFollow(object)) return await acceptFollow(actor, object);
 
-	default:
-		logger.warn(`Unknown accept type: ${object.type}`);
-		break;
-	}
+	return `skip: Unknown Accept type: ${getApType(object)}`;
 };
diff --git a/src/remote/activitypub/kernel/create/index.ts b/src/remote/activitypub/kernel/create/index.ts
index 108cfedf41..f1a3ebff43 100644
--- a/src/remote/activitypub/kernel/create/index.ts
+++ b/src/remote/activitypub/kernel/create/index.ts
@@ -1,7 +1,7 @@
 import Resolver from '../../resolver';
 import { IRemoteUser } from '../../../../models/entities/user';
 import createNote from './note';
-import { ICreate, getApId, validPost } from '../../type';
+import { ICreate, getApId, isPost, getApType } from '../../type';
 import { apLogger } from '../../logger';
 import { toArray, concat, unique } from '../../../../prelude/array';
 
@@ -35,9 +35,9 @@ export default async (actor: IRemoteUser, activity: ICreate): Promise<void> => {
 		throw e;
 	});
 
-	if (validPost.includes(object.type)) {
+	if (isPost(object)) {
 		createNote(resolver, actor, object, false, activity);
 	} else {
-		logger.warn(`Unknown type: ${object.type}`);
+		logger.warn(`Unknown type: ${getApType(object)}`);
 	}
 };
diff --git a/src/remote/activitypub/kernel/reject/index.ts b/src/remote/activitypub/kernel/reject/index.ts
index 96e9aadf5d..d7a80fce7b 100644
--- a/src/remote/activitypub/kernel/reject/index.ts
+++ b/src/remote/activitypub/kernel/reject/index.ts
@@ -1,12 +1,12 @@
 import Resolver from '../../resolver';
 import { IRemoteUser } from '../../../../models/entities/user';
 import rejectFollow from './follow';
-import { IReject, IFollow } from '../../type';
+import { IReject, isFollow, getApType } from '../../type';
 import { apLogger } from '../../logger';
 
 const logger = apLogger;
 
-export default async (actor: IRemoteUser, activity: IReject): Promise<void> => {
+export default async (actor: IRemoteUser, activity: IReject): Promise<string> => {
 	const uri = activity.id || activity;
 
 	logger.info(`Reject: ${uri}`);
@@ -18,13 +18,7 @@ export default async (actor: IRemoteUser, activity: IReject): Promise<void> => {
 		throw e;
 	});
 
-	switch (object.type) {
-	case 'Follow':
-		rejectFollow(actor, object as IFollow);
-		break;
+	if (isFollow(object)) return await rejectFollow(actor, object);
 
-	default:
-		logger.warn(`Unknown reject type: ${object.type}`);
-		break;
-	}
+	return `skip: Unknown Reject type: ${getApType(object)}`;
 };
diff --git a/src/remote/activitypub/kernel/undo/announce.ts b/src/remote/activitypub/kernel/undo/announce.ts
index 38ce5b6c59..e08fea188d 100644
--- a/src/remote/activitypub/kernel/undo/announce.ts
+++ b/src/remote/activitypub/kernel/undo/announce.ts
@@ -3,14 +3,15 @@ import { IRemoteUser } from '../../../../models/entities/user';
 import { IAnnounce, getApId } from '../../type';
 import deleteNote from '../../../../services/note/delete';
 
-export const undoAnnounce = async (actor: IRemoteUser, activity: IAnnounce): Promise<void> => {
+export const undoAnnounce = async (actor: IRemoteUser, activity: IAnnounce): Promise<string> => {
 	const uri = getApId(activity);
 
 	const note = await Notes.findOne({
 		uri
 	});
 
-	if (!note) return;
+	if (!note) return 'skip: no such Announce';
 
 	await deleteNote(actor, note);
+	return 'ok: deleted';
 };
diff --git a/src/remote/activitypub/kernel/undo/index.ts b/src/remote/activitypub/kernel/undo/index.ts
index 93909352d9..0bab3c9666 100644
--- a/src/remote/activitypub/kernel/undo/index.ts
+++ b/src/remote/activitypub/kernel/undo/index.ts
@@ -1,5 +1,5 @@
 import { IRemoteUser } from '../../../../models/entities/user';
-import { IUndo, IFollow, IBlock, ILike, IAnnounce } from '../../type';
+import { IUndo, isFollow, isBlock, isLike, isAnnounce, getApType } from '../../type';
 import unfollow from './follow';
 import unblock from './block';
 import undoLike from './like';
@@ -9,7 +9,7 @@ import { apLogger } from '../../logger';
 
 const logger = apLogger;
 
-export default async (actor: IRemoteUser, activity: IUndo): Promise<void> => {
+export default async (actor: IRemoteUser, activity: IUndo): Promise<string> => {
 	if ('actor' in activity && actor.uri !== activity.actor) {
 		throw new Error('invalid actor');
 	}
@@ -25,20 +25,10 @@ export default async (actor: IRemoteUser, activity: IUndo): Promise<void> => {
 		throw e;
 	});
 
-	switch (object.type) {
-		case 'Follow':
-			unfollow(actor, object as IFollow);
-			break;
-		case 'Block':
-			unblock(actor, object as IBlock);
-			break;
-		case 'Like':
-		case 'EmojiReaction':
-		case 'EmojiReact':
-			undoLike(actor, object as ILike);
-			break;
-		case 'Announce':
-			undoAnnounce(actor, object as IAnnounce);
-			break;
-	}
+	if (isFollow(object)) return await unfollow(actor, object);
+	if (isBlock(object)) return await unblock(actor, object);
+	if (isLike(object)) return await undoLike(actor, object);
+	if (isAnnounce(object)) return await undoAnnounce(actor, object);
+
+	return `skip: unknown object type ${getApType(object)}`;
 };
diff --git a/src/remote/activitypub/kernel/update/index.ts b/src/remote/activitypub/kernel/update/index.ts
index ea7e6a063e..6dd3e5f296 100644
--- a/src/remote/activitypub/kernel/update/index.ts
+++ b/src/remote/activitypub/kernel/update/index.ts
@@ -1,5 +1,5 @@
 import { IRemoteUser } from '../../../../models/entities/user';
-import { IUpdate, validActor } from '../../type';
+import { getApType, IUpdate, isActor } from '../../type';
 import { apLogger } from '../../logger';
 import { updateQuestion } from '../../models/question';
 import Resolver from '../../resolver';
@@ -22,13 +22,13 @@ export default async (actor: IRemoteUser, activity: IUpdate): Promise<string> =>
 		throw e;
 	});
 
-	if (validActor.includes(object.type)) {
+	if (isActor(object)) {
 		await updatePerson(actor.uri!, resolver, object);
 		return `ok: Person updated`;
-	} else if (object.type === 'Question') {
+	} else if (getApType(object) === 'Question') {
 		await updateQuestion(object).catch(e => console.log(e));
 		return `ok: Question updated`;
 	} else {
-		return `skip: Unknown type: ${object.type}`;
+		return `skip: Unknown type: ${getApType(object)}`;
 	}
 };
diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts
index 09e066708f..3b7452c3cb 100644
--- a/src/remote/activitypub/models/note.ts
+++ b/src/remote/activitypub/models/note.ts
@@ -17,7 +17,7 @@ import { deliverQuestionUpdate } from '../../../services/note/polls/update';
 import { extractDbHost, toPuny } from '@/misc/convert-host';
 import { Emojis, Polls, MessagingMessages } from '../../../models';
 import { Note } from '../../../models/entities/note';
-import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, isEmoji } from '../type';
+import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, isEmoji, getApType } from '../type';
 import { Emoji } from '../../../models/entities/emoji';
 import { genId } from '@/misc/gen-id';
 import { fetchMeta } from '@/misc/fetch-meta';
@@ -36,8 +36,8 @@ export function validateNote(object: any, uri: string) {
 		return new Error('invalid Note: object is null');
 	}
 
-	if (!validPost.includes(object.type)) {
-		return new Error(`invalid Note: invalid object type ${object.type}`);
+	if (!validPost.includes(getApType(object))) {
+		return new Error(`invalid Note: invalid object type ${getApType(object)}`);
 	}
 
 	if (object.id && extractDbHost(object.id) !== expectHost) {
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index 5b032d9d9c..1062fe2995 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -4,7 +4,7 @@ import * as promiseLimit from 'promise-limit';
 import config from '@/config';
 import Resolver from '../resolver';
 import { resolveImage } from './image';
-import { isCollectionOrOrderedCollection, isCollection, IPerson, getApId, getOneApHrefNullable, IObject, isPropertyValue, IApPropertyValue } from '../type';
+import { isCollectionOrOrderedCollection, isCollection, IPerson, getApId, getOneApHrefNullable, IObject, isPropertyValue, IApPropertyValue, getApType } from '../type';
 import { fromHtml } from '../../../mfm/from-html';
 import { htmlToMfm } from '../misc/html-to-mfm';
 import { resolveNote, extractEmojis } from './note';
@@ -137,7 +137,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 
 	const tags = extractApHashtags(person.tag).map(tag => normalizeForSearch(tag)).splice(0, 32);
 
-	const isBot = object.type === 'Service';
+	const isBot = getApType(object) === 'Service';
 
 	const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/);
 
@@ -337,7 +337,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
 		emojis: emojiNames,
 		name: person.name,
 		tags,
-		isBot: object.type === 'Service',
+		isBot: getApType(object) === 'Service',
 		isCat: (person as any).isCat === true,
 		isLocked: !!person.manuallyApprovesFollowers,
 		isExplorable: !!person.discoverable,
@@ -476,7 +476,7 @@ export async function updateFeatured(userId: User['id']) {
 	// Resolve and regist Notes
 	const limit = promiseLimit<Note | null>(2);
 	const featuredNotes = await Promise.all(items
-		.filter(item => item.type === 'Note')
+		.filter(item => getApType(item) === 'Note')	// TODO: Noteでなくてもいいかも
 		.slice(0, 5)
 		.map(item => limit(() => resolveNote(item, resolver))));
 
diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts
index db866ae67a..98025da908 100644
--- a/src/remote/activitypub/type.ts
+++ b/src/remote/activitypub/type.ts
@@ -3,7 +3,7 @@ export type ApObject = IObject | string | (IObject | string)[];
 
 export interface IObject {
 	'@context': string | obj | obj[];
-	type: string;
+	type: string | unknown[];
 	id?: string;
 	summary?: string;
 	published?: string;
@@ -51,6 +51,15 @@ export function getApId(value: string | IObject): string {
 	throw new Error(`cannot detemine id`);
 }
 
+/**
+ * Get ActivityStreams Object type
+ */
+export function getApType(value: IObject): string {
+	if (typeof value.type === 'string') return value.type;
+	if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0];
+	throw new Error(`cannot detect type`);
+}
+
 export function getOneApHrefNullable(value: ApObject | undefined): string | undefined {
 	const firstOne = Array.isArray(value) ? value[0] : value;
 	return getApHrefNullable(firstOne);
@@ -92,6 +101,9 @@ export interface IOrderedCollection extends IObject {
 
 export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event'];
 
+export const isPost = (object: IObject): object is IPost =>
+	validPost.includes(getApType(object));
+
 export interface IPost extends IObject {
 	type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event';
 	_misskey_content?: string;
@@ -112,7 +124,7 @@ export interface IQuestion extends IObject {
 }
 
 export const isQuestion = (object: IObject): object is IQuestion =>
-	object.type === 'Note' || object.type === 'Question';
+	getApType(object) === 'Note' || getApType(object) === 'Question';
 
 interface IQuestionChoice {
 	name?: string;
@@ -126,10 +138,13 @@ export interface ITombstone extends IObject {
 }
 
 export const isTombstone = (object: IObject): object is ITombstone =>
-	object.type === 'Tombstone';
+	getApType(object) === 'Tombstone';
 
 export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application'];
 
+export const isActor = (object: IObject): object is IPerson =>
+	validActor.includes(getApType(object));
+
 export interface IPerson extends IObject {
 	type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application';
 	name?: string;
@@ -154,10 +169,10 @@ export interface IPerson extends IObject {
 }
 
 export const isCollection = (object: IObject): object is ICollection =>
-	object.type === 'Collection';
+	getApType(object) === 'Collection';
 
 export const isOrderedCollection = (object: IObject): object is IOrderedCollection =>
-	object.type === 'OrderedCollection';
+	getApType(object) === 'OrderedCollection';
 
 export const isCollectionOrOrderedCollection = (object: IObject): object is ICollection | IOrderedCollection =>
 	isCollection(object) || isOrderedCollection(object);
@@ -171,7 +186,7 @@ export interface IApPropertyValue extends IObject {
 
 export const isPropertyValue = (object: IObject): object is IApPropertyValue =>
 	object &&
-	object.type === 'PropertyValue' &&
+	getApType(object) === 'PropertyValue' &&
 	typeof object.name === 'string' &&
 	typeof (object as any).value === 'string';
 
@@ -181,7 +196,7 @@ export interface IApMention extends IObject {
 }
 
 export const isMention = (object: IObject): object is IApMention=>
-	object.type === 'Mention' &&
+	getApType(object) === 'Mention' &&
 	typeof object.href === 'string';
 
 export interface IApHashtag extends IObject {
@@ -190,7 +205,7 @@ export interface IApHashtag extends IObject {
 }
 
 export const isHashtag = (object: IObject): object is IApHashtag =>
-	object.type === 'Hashtag' &&
+	getApType(object) === 'Hashtag' &&
 	typeof object.name === 'string';
 
 export interface IApEmoji extends IObject {
@@ -199,7 +214,7 @@ export interface IApEmoji extends IObject {
 }
 
 export const isEmoji = (object: IObject): object is IApEmoji =>
-	object.type === 'Emoji' && !Array.isArray(object.icon) && object.icon.url != null;
+	getApType(object) === 'Emoji' && !Array.isArray(object.icon) && object.icon.url != null;
 
 export interface ICreate extends IActivity {
 	type: 'Create';
@@ -258,17 +273,17 @@ export interface IFlag extends IActivity {
 	type: 'Flag';
 }
 
-export const isCreate = (object: IObject): object is ICreate => object.type === 'Create';
-export const isDelete = (object: IObject): object is IDelete => object.type === 'Delete';
-export const isUpdate = (object: IObject): object is IUpdate => object.type === 'Update';
-export const isRead = (object: IObject): object is IRead => object.type === 'Read';
-export const isUndo = (object: IObject): object is IUndo => object.type === 'Undo';
-export const isFollow = (object: IObject): object is IFollow => object.type === 'Follow';
-export const isAccept = (object: IObject): object is IAccept => object.type === 'Accept';
-export const isReject = (object: IObject): object is IReject => object.type === 'Reject';
-export const isAdd = (object: IObject): object is IAdd => object.type === 'Add';
-export const isRemove = (object: IObject): object is IRemove => object.type === 'Remove';
-export const isLike = (object: IObject): object is ILike => object.type === 'Like' || object.type === 'EmojiReaction' || object.type === 'EmojiReact';
-export const isAnnounce = (object: IObject): object is IAnnounce => object.type === 'Announce';
-export const isBlock = (object: IObject): object is IBlock => object.type === 'Block';
-export const isFlag = (object: IObject): object is IFlag => object.type === 'Flag';
+export const isCreate = (object: IObject): object is ICreate => getApType(object) === 'Create';
+export const isDelete = (object: IObject): object is IDelete => getApType(object) === 'Delete';
+export const isUpdate = (object: IObject): object is IUpdate => getApType(object) === 'Update';
+export const isRead = (object: IObject): object is IRead => getApType(object) === 'Read';
+export const isUndo = (object: IObject): object is IUndo => getApType(object) === 'Undo';
+export const isFollow = (object: IObject): object is IFollow => getApType(object) === 'Follow';
+export const isAccept = (object: IObject): object is IAccept => getApType(object) === 'Accept';
+export const isReject = (object: IObject): object is IReject => getApType(object) === 'Reject';
+export const isAdd = (object: IObject): object is IAdd => getApType(object) === 'Add';
+export const isRemove = (object: IObject): object is IRemove => getApType(object) === 'Remove';
+export const isLike = (object: IObject): object is ILike => getApType(object) === 'Like' || getApType(object) === 'EmojiReaction' || getApType(object) === 'EmojiReact';
+export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce';
+export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block';
+export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag';
diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts
index 2ce11160e8..b4df1ad4d7 100644
--- a/src/server/api/endpoints/ap/show.ts
+++ b/src/server/api/endpoints/ap/show.ts
@@ -10,7 +10,7 @@ import { Users, Notes } from '../../../../models';
 import { Note } from '../../../../models/entities/note';
 import { User } from '../../../../models/entities/user';
 import { fetchMeta } from '@/misc/fetch-meta';
-import { validActor, validPost } from '../../../../remote/activitypub/type';
+import { isActor, isPost, getApId } from '../../../../remote/activitypub/type';
 
 export const meta = {
 	tags: ['federation'],
@@ -154,16 +154,16 @@ async function fetchAny(uri: string) {
 	}
 
 	// それでもみつからなければ新規であるため登録
-	if (validActor.includes(object.type)) {
-		const user = await createPerson(object.id);
+	if (isActor(object)) {
+		const user = await createPerson(getApId(object));
 		return {
 			type: 'User',
 			object: await Users.pack(user, null, { detail: true })
 		};
 	}
 
-	if (validPost.includes(object.type)) {
-		const note = await createNote(object.id, undefined, true);
+	if (isPost(object)) {
+		const note = await createNote(getApId(object), undefined, true);
 		return {
 			type: 'Note',
 			object: await Notes.pack(note!, null, { detail: true })

From 3e7a87f75afdfe8001ecd3354c5170d9e57f9f98 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 31 May 2021 13:06:25 +0900
Subject: [PATCH 28/28] 12.82.0

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

diff --git a/package.json b/package.json
index ca33644052..68f9bd75bb 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
 	"name": "misskey",
 	"author": "syuilo <syuilotan@yahoo.co.jp>",
-	"version": "12.81.2",
+	"version": "12.82.0",
 	"codename": "indigo",
 	"repository": {
 		"type": "git",