From 30df8ea1213013072f139aa26a635330457cf2bc Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 29 Jul 2020 01:15:02 +0900
Subject: [PATCH] =?UTF-8?q?feat(client):=20AiScript:=20=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88API?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 package.json                       |  2 +-
 src/client/components/note.vue     | 16 +++++++++++++---
 src/client/scripts/aiscript/api.ts |  3 +++
 src/client/store.ts                |  9 +++++++++
 yarn.lock                          |  8 ++++----
 5 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index 376ee7105e..30a23c620f 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
 		"@koa/multer": "3.0.0",
 		"@koa/router": "9.0.1",
 		"@sinonjs/fake-timers": "6.0.1",
-		"@syuilo/aiscript": "0.8.0",
+		"@syuilo/aiscript": "0.9.0",
 		"@types/bcryptjs": "2.4.2",
 		"@types/bull": "3.14.0",
 		"@types/cbor": "5.0.0",
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index c3a199a805..a359287b41 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -35,19 +35,19 @@
 		</div>
 	</div>
 	<article class="article">
-		<mk-avatar class="avatar" :user="appearNote.user" v-once/>
+		<mk-avatar class="avatar" :user="appearNote.user"/>
 		<div class="main">
 			<x-note-header class="header" :note="appearNote" :mini="true"/>
 			<div class="body" ref="noteBody">
 				<p v-if="appearNote.cw != null" class="cw">
-				<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/>
+				<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis"/>
 					<x-cw-button v-model="showContent" :note="appearNote"/>
 				</p>
 				<div class="content" v-show="appearNote.cw == null || showContent">
 					<div class="text">
 						<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span>
 						<router-link class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><fa :icon="faReply"/></router-link>
-						<mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/>
+						<mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis"/>
 						<a class="rp" v-if="appearNote.renote != null">RN:</a>
 					</div>
 					<div class="files" v-if="appearNote.files.length > 0">
@@ -114,6 +114,7 @@ import { focusPrev, focusNext } from '../scripts/focus';
 import { url } from '../config';
 import copyToClipboard from '../scripts/copy-to-clipboard';
 import { checkWordMute } from '../scripts/check-word-mute';
+import { utils } from '@syuilo/aiscript';
 
 export default Vue.extend({
 	model: {
@@ -246,6 +247,15 @@ export default Vue.extend({
 			this.connection = this.$root.stream;
 		}
 
+		// plugin
+		if (this.$store.state.noteViewInterruptors.length > 0) {
+			let result = this.note;
+			for (const interruptor of this.$store.state.noteViewInterruptors) {
+				result = utils.valToJs(await interruptor.handler(JSON.parse(JSON.stringify(result))));
+			}
+			this.$emit('updated', Object.freeze(result));
+		}
+
 		this.muted = await checkWordMute(this.appearNote, this.$store.state.i, this.$store.state.settings.mutedWords);
 
 		if (this.detail) {
diff --git a/src/client/scripts/aiscript/api.ts b/src/client/scripts/aiscript/api.ts
index bfbfe8d59d..90418fc5ca 100644
--- a/src/client/scripts/aiscript/api.ts
+++ b/src/client/scripts/aiscript/api.ts
@@ -70,6 +70,9 @@ export function createPluginEnv(vm, opts) {
 		'Plugin:register_note_action': values.FN_NATIVE(([title, handler]) => {
 			vm.$store.commit('registerNoteAction', { pluginId: opts.plugin.id, title: title.value, handler });
 		}),
+		'Plugin:register_note_view_interruptor': values.FN_NATIVE(([handler]) => {
+			vm.$store.commit('registerNoteViewInterruptor', { pluginId: opts.plugin.id, handler });
+		}),
 		'Plugin:config': values.OBJ(config),
 	};
 }
diff --git a/src/client/store.ts b/src/client/store.ts
index 67dd6ea06a..7046e10f98 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -111,6 +111,7 @@ export default () => new Vuex.Store({
 		postFormActions: [],
 		userActions: [],
 		noteActions: [],
+		noteViewInterruptors: [],
 	},
 
 	getters: {
@@ -274,6 +275,14 @@ export default () => new Vuex.Store({
 				}
 			});
 		},
+
+		registerNoteViewInterruptor(state, { pluginId, handler }) {
+			state.noteViewInterruptors.push({
+				handler: (note) => {
+					return state.pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)]);
+				}
+			});
+		},
 	},
 
 	actions: {
diff --git a/yarn.lock b/yarn.lock
index 082f8b4dd8..10554e567d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -192,10 +192,10 @@
   dependencies:
     "@sinonjs/commons" "^1.7.0"
 
-"@syuilo/aiscript@0.8.0":
-  version "0.8.0"
-  resolved "https://registry.yarnpkg.com/@syuilo/aiscript/-/aiscript-0.8.0.tgz#3a895ddd9f5bd5afa1648acb5fd3e6f94f434cbb"
-  integrity sha512-mrZ3awYf1R81D+OWZctRFiAWUt6xL3A5ovBn2OD8+1hZyX3T7S+awqrhYVLoQPhd/cijz1RT6PE8AEUtuR1J8Q==
+"@syuilo/aiscript@0.9.0":
+  version "0.9.0"
+  resolved "https://registry.yarnpkg.com/@syuilo/aiscript/-/aiscript-0.9.0.tgz#95f260989ce1d9d4af49f116a4cc0c30360fcdad"
+  integrity sha512-yv/IQgpcAjyKzd8Q87ANAraISOc7X3SHkXUNc3Asv5ABZ4hx8m62+CnPcrNabIuG2PYRnPGef4ImUpavg6C6Ng==
   dependencies:
     autobind-decorator "2.4.0"
     chalk "4.0.0"