From f51bca41c5f59f9ffce346a3ec32badaf1ccda31 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 21 Oct 2023 18:41:12 +0900 Subject: Feat: 外部サイトからテーマ・プラグインのインストールができるように (#12034) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat: 外部サイトからテーマ・プラグインのインストールができるように * Update Changelog * Change Changelog * Remove unnecessary imports * Update fetch-external-resources.ts * Update CHANGELOG.md * Update CHANGELOG.md --- packages/frontend/src/scripts/install-plugin.ts | 129 ++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 packages/frontend/src/scripts/install-plugin.ts (limited to 'packages/frontend/src/scripts/install-plugin.ts') diff --git a/packages/frontend/src/scripts/install-plugin.ts b/packages/frontend/src/scripts/install-plugin.ts new file mode 100644 index 0000000000..1310a0dc73 --- /dev/null +++ b/packages/frontend/src/scripts/install-plugin.ts @@ -0,0 +1,129 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineAsyncComponent } from 'vue'; +import { compareVersions } from 'compare-versions'; +import { v4 as uuid } from 'uuid'; +import { Interpreter, Parser, utils } from '@syuilo/aiscript'; +import type { Plugin } from '@/store.js'; +import { ColdDeviceStorage } from '@/store.js'; +import * as os from '@/os.js'; +import { i18n } from '@/i18n.js'; + +export type AiScriptPluginMeta = { + name: string; + version: string; + author: string; + description?: string; + permissions?: string[]; + config?: Record; +}; + +const parser = new Parser(); + +export function savePlugin({ id, meta, src, token }: { + id: string; + meta: AiScriptPluginMeta; + src: string; + token: string; +}) { + ColdDeviceStorage.set('plugins', ColdDeviceStorage.get('plugins').concat({ + ...meta, + id, + active: true, + configData: {}, + token: token, + src: src, + } as Plugin)); +} + +export function isSupportedAiScriptVersion(version: string): boolean { + try { + return (compareVersions(version, '0.12.0') >= 0); + } catch (err) { + return false; + } +} + +export async function parsePluginMeta(code: string): Promise { + if (!code) { + throw new Error('code is required'); + } + + const lv = utils.getLangVersion(code); + if (lv == null) { + throw new Error('No language version annotation found'); + } else if (!isSupportedAiScriptVersion(lv)) { + throw new Error(`Aiscript version '${lv}' is not supported`); + } + + let ast; + try { + ast = parser.parse(code); + } catch (err) { + throw new Error('Aiscript syntax error'); + } + + const meta = Interpreter.collectMetadata(ast); + if (meta == null) { + throw new Error('Meta block not found'); + } + + const metadata = meta.get(null); + if (metadata == null) { + throw new Error('Metadata not found'); + } + + const { name, version, author, description, permissions, config } = metadata; + if (name == null || version == null || author == null) { + throw new Error('Required property not found'); + } + + return { + name, + version, + author, + description, + permissions, + config, + }; +} + +export async function installPlugin(code: string, meta?: AiScriptPluginMeta) { + if (!code) return; + + let realMeta: AiScriptPluginMeta; + if (!meta) { + realMeta = await parsePluginMeta(code); + } else { + realMeta = meta; + } + + const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => { + os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), { + title: i18n.ts.tokenRequested, + information: i18n.ts.pluginTokenRequestedDescription, + initialName: realMeta.name, + initialPermissions: realMeta.permissions, + }, { + done: async result => { + const { name, permissions } = result; + const { token } = await os.api('miauth/gen-token', { + session: null, + name: name, + permission: permissions, + }); + res(token); + }, + }, 'closed'); + }); + + savePlugin({ + id: uuid(), + meta: realMeta, + token, + src: code, + }); +} -- cgit v1.2.3-freya