From aeeda0f710c9c22d1507d3edfb2b5e08a1bdc1e8 Mon Sep 17 00:00:00 2001 From: CodFrm Date: Fri, 14 Jan 2022 18:43:45 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E8=84=9A=E6=9C=AC=E9=9D=99?= =?UTF-8?q?=E9=BB=98=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apps/script/manager.ts | 284 ++++++++++++++----------- src/pkg/config.ts | 23 +- src/views/pages/Option/tabs/Config.vue | 9 + 3 files changed, 183 insertions(+), 133 deletions(-) diff --git a/src/apps/script/manager.ts b/src/apps/script/manager.ts index 0bf26723..1f34554c 100644 --- a/src/apps/script/manager.ts +++ b/src/apps/script/manager.ts @@ -1,12 +1,12 @@ import axios from 'axios'; import { MsgCenter } from '@App/apps/msg-center/msg-center'; import { AppEvent, ScriptExec, ScriptRunStatusChange, ScriptStatusChange, ScriptStop, ScriptUninstall, ScriptReinstall, ScriptValueChange, TabRemove, RequestTabRunScript, ScriptInstall, RequestInstallInfo, ScriptCheckUpdate, RequestConfirmInfo, ListenGmLog, SubscribeUpdate, Unsubscribe, SubscribeCheckUpdate, OpenImportFileWindow, RequestImportFile, ScriptInstallByURL } from '@App/apps/msg-center/event'; -import { dealScript, get, randomString } from '@App/pkg/utils/utils'; +import { dealScript, get, InfoNotification, randomString } from '@App/pkg/utils/utils'; import { App } from '../app'; import { UrlMatch } from '@App/pkg/match'; import { ValueModel } from '@App/model/value'; import { ResourceManager } from '../resource'; -import { ScriptCache, Script, SCRIPT_STATUS_ENABLE, SCRIPT_STATUS_DISABLE, SCRIPT_TYPE_CRONTAB, SCRIPT_TYPE_BACKGROUND, SCRIPT_RUN_STATUS_RUNNING, SCRIPT_RUN_STATUS_COMPLETE, SCRIPT_TYPE_NORMAL, SCRIPT_STATUS_ERROR, SCRIPT_RUN_STATUS_RETRY, SCRIPT_RUN_STATUS_ERROR, SCRIPT_STATUS_DELETE } from '@App/model/do/script'; +import { ScriptCache, Script, SCRIPT_STATUS_ENABLE, SCRIPT_STATUS_DISABLE, SCRIPT_TYPE_CRONTAB, SCRIPT_TYPE_BACKGROUND, SCRIPT_RUN_STATUS_RUNNING, SCRIPT_RUN_STATUS_COMPLETE, SCRIPT_TYPE_NORMAL, SCRIPT_STATUS_ERROR, SCRIPT_RUN_STATUS_RETRY, SCRIPT_RUN_STATUS_ERROR, SCRIPT_STATUS_DELETE, Metadata } from '@App/model/do/script'; import { Value } from '@App/model/do/value'; import { ScriptModel } from '@App/model/script'; import { Background } from './background'; @@ -21,6 +21,7 @@ import { SyncModel } from '@App/model/sync'; import { SyncAction, SyncData } from '@App/model/do/sync'; import { v4 as uuidv4 } from 'uuid'; import { Manager } from '@App/pkg/apps/manager'; +import { SystemConfig } from '@App/pkg/config'; // 脚本管理器,收到控制器消息进行实际的操作 export class ScriptManager extends Manager { @@ -225,18 +226,18 @@ export class ScriptManager extends Manager { } // 检查订阅规则是否改变,是否能够静默更新 - public checkSubscribeRule(oldSub: Subscribe, newSub: Subscribe): boolean { + public checkUpdateRule(oldMeta: Metadata, newMeta: Metadata): boolean { //判断connect是否改变 const oldConnect = new Map(); const newConnect = new Map(); - oldSub.metadata['connect'] && oldSub.metadata['connect'].forEach(val => { + oldMeta['connect'] && oldMeta['connect'].forEach(val => { oldConnect.set(val, 1); }); - newSub.metadata['connect'] && newSub.metadata['connect'].forEach(val => { + newMeta['connect'] && newMeta['connect'].forEach(val => { newConnect.set(val, 1); }); // 老的里面没有新的就需要用户确认了 - for (const key in newConnect) { + for (const key of newConnect.keys()) { if (!oldConnect.has(key)) { return false } @@ -266,81 +267,88 @@ export class ScriptManager extends Manager { } public subscribeCheckUpdate(subscribeId: number): Promise { - return new Promise(async resolve => { - const sub = await this.subscribeModel.findById(subscribeId); - if (!sub) { - return resolve(false); - } - this.subscribeModel.table.update(sub.id, { checktime: new Date().getTime() }); - axios.get(sub.url, { - headers: { - 'Cache-Control': 'no-cache' - } - }).then((response): string | null => { - if (response.status != 200) { - App.Log.Warn('check subscribe', 'subscribe:' + sub.id + ' error: respond:' + response.statusText, sub.name); - return null; - } - const metadata = parseMetadata(response.data); - if (metadata == null) { - App.Log.Error('check subscribe', 'MetaData信息错误', sub.name); - return null; - } - if (!sub.metadata['version']) { - sub.metadata['version'] = ['v0.0.0']; - } - if (!metadata['version']) { - return null; - } - const regexp = /[0-9]+/g - let oldVersion = sub.metadata['version'][0].match(regexp); - if (!oldVersion) { - oldVersion = ['0', '0', '0']; - } - const Version = metadata['version'][0].match(regexp); - if (!Version) { - App.Log.Warn('check subscribe', '订阅脚本version格式错误:' + sub.id, sub.name); - return null; + return new Promise(resolve => { + const handler = async () => { + const sub = await this.subscribeModel.findById(subscribeId); + if (!sub) { + return resolve(false); } - for (let i = 0; i < Version.length; i++) { - if (oldVersion[i] == undefined) { - return response.data; + void this.subscribeModel.table.update(sub.id, { checktime: new Date().getTime() }); + axios.get(sub.url, { + responseType: 'text', + headers: { + 'Cache-Control': 'no-cache' } - if (parseInt(Version[i]) > parseInt(oldVersion[i])) { - return response.data; + }).then(async (response): Promise<[Subscribe, Subscribe] | null> => { + if (response.status != 200) { + App.Log.Warn('check subscribe', 'subscribe:' + sub.id.toString() + ' error: respond:' + response.statusText, sub.name); + return null; } - } - return null; - }).then(async (val: string | null) => { - // TODO: 解析了不知道多少次,有时间优化 - if (val) { - const [newSub, oldSub] = await this.controller.prepareSubscribeByCode(val, sub.url); - if (newSub) { + const [newSub, oldSub] = await this.controller.prepareSubscribeByCode(response.data, sub.url); + if (typeof oldSub == 'string') { + App.Log.Error('check subscribe', oldSub, sub.name); + return null; + } + if (!newSub) { + App.Log.Error('check subscribe', '未知错误', sub.name); + return null; + } + if (!sub.metadata['version']) { + sub.metadata['version'] = ['v0.0.0']; + } + if (!newSub.metadata['version']) { + return null; + } + const regexp = /[0-9]+/g + let oldVersion = sub.metadata['version'][0].match(regexp); + if (!oldVersion) { + oldVersion = ['0', '0', '0']; + } + const Version = newSub.metadata['version'][0].match(regexp); + if (!Version) { + App.Log.Warn('check subscribe', '订阅脚本version格式错误:' + sub.id.toString(), sub.name); + return null; + } + for (let i = 0; i < Version.length; i++) { + if (oldVersion[i] == undefined) { + return [newSub, sub]; + } + if (parseInt(Version[i]) > parseInt(oldVersion[i])) { + return [newSub, sub]; + } + } + return null; + }).then(async (val: [Subscribe | undefined, Subscribe | undefined] | null) => { + // TODO: 解析了不知道多少次,有时间优化 + if (val) { // 规则通过静默更新,未通过打开窗口 - if (this.checkSubscribeRule(oldSub, newSub)) { - this.subscribeUpdate(newSub, oldSub); + const oldSub = val[1], newSub = val[0]; + if (this.checkUpdateRule(oldSub.metadata, newSub.metadata)) { + void this.subscribeUpdate(newSub, oldSub); } else { const info = await loadScriptByUrl(sub.url); if (info) { - App.Cache.set('install:info:' + info.uuid, info); + void App.Cache.set('install:info:' + info.uuid, info); chrome.tabs.create({ url: 'install.html?uuid=' + info.uuid, active: false, }); } } + resolve(true); + } else { + resolve(false); } - resolve(true); - } else { + }).catch((e: string) => { resolve(false); - } - }).catch((e) => { - App.Log.Warn('check subscribe', 'subscribe:' + sub.id + ' error: ' + e, sub.name); - resolve(false); - }); + App.Log.Warn('check subscribe', 'subscribe:' + sub.id.toString() + ' error: ' + e, sub.name); + }); + } + void handler(); }); } + public subscribeUpdate(sub: Subscribe, old: Subscribe | undefined, changeRule?: boolean): Promise { return new Promise(async resolve => { // 异步处理订阅 @@ -926,73 +934,99 @@ export class ScriptManager extends Manager { // 检查脚本更新 public scriptCheckUpdate(scriptId: number): Promise { - return new Promise(async resolve => { - const script = await this.getScript(scriptId); - if (!script) { - return resolve(false); - } - if (!script.checkupdate_url) { - return resolve(false); - } - this.scriptModel.table.update(script.id, { checktime: new Date().getTime() }); - axios.get(script.checkupdate_url, { - headers: { - 'Cache-Control': 'no-cache' - } - }).then((response): boolean => { - if (response.status != 200) { - App.Log.Warn('check update', 'script:' + script.id + ' error: respond:' + response.statusText, script.name); - return false; - } - const meta = parseMetadata(response.data); - if (!meta) { - App.Log.Warn('check update', 'script:' + script.id + ' error: metadata format', script.name); - return false; - } - if (!script.metadata['version']) { - script.metadata['version'] = ['0.0.0']; - } - if (!meta['version']) { - return false; - } - const regexp = /[0-9]+/g - let oldVersion = script.metadata['version'][0].match(regexp); - if (!oldVersion) { - oldVersion = ['0', '0', '0']; + return new Promise(resolve => { + const handler = async () => { + const script = await this.getScript(scriptId); + if (!script) { + return resolve(false); } - const Version = meta['version'][0].match(regexp); - if (!Version) { - App.Log.Warn('check update', 'script:' + script.id + ' error: version format', script.name); - return false; + if (!script.checkupdate_url) { + return resolve(false); } - for (let i = 0; i < Version.length; i++) { - if (oldVersion[i] == undefined) { - return true; + void this.scriptModel.table.update(script.id, { checktime: new Date().getTime() }); + axios.get(script.checkupdate_url, { + responseType: 'text', + headers: { + 'Cache-Control': 'no-cache' } - if (parseInt(Version[i]) > parseInt(oldVersion[i])) { - return true; + }).then(async (response): Promise<[Script, Script] | null> => { + if (response.status != 200) { + App.Log.Warn('check update', 'script:' + script.id.toString() + ' error: respond:' + response.statusText, script.name); + return null; } - } - return false; - }).then(async (val) => { - if (val) { - const info = await loadScriptByUrl(script.download_url || script.origin); - if (info) { - info.url = script.origin; - info.uuid = uuidv5(info.url, uuidv5.URL) - App.Cache.set('install:info:' + info.uuid, info); - chrome.tabs.create({ - url: 'install.html?uuid=' + info.uuid, - active: false, - }); + const [newScript, oldScript] = await this.controller.prepareScriptByCode(response.data, script.download_url, script.uuid); + if (typeof oldScript == 'string') { + App.Log.Error('check update', oldScript, script.name); + return null; } - } - resolve(val); - }).catch((e) => { - App.Log.Warn('check update', 'script:' + script.id + ' error: ' + e, script.name); - resolve(false); - }); - + if (!newScript) { + App.Log.Error('check update', '未知错误', script.name); + return null; + } + if (!script.metadata['version']) { + script.metadata['version'] = ['0.0.0']; + } + if (!newScript.metadata['version']) { + return null; + } + const regexp = /[0-9]+/g + let oldVersion = script.metadata['version'][0].match(regexp); + if (!oldVersion) { + oldVersion = ['0', '0', '0']; + } + const Version = newScript.metadata['version'][0].match(regexp); + if (!Version) { + App.Log.Warn('check update', 'script:' + script.id.toString() + ' error: version format', script.name); + return null; + } + for (let i = 0; i < Version.length; i++) { + if (oldVersion[i] == undefined) { + return [newScript, script]; + } + if (parseInt(Version[i]) > parseInt(oldVersion[i])) { + return [newScript, script]; + } + } + return null; + }).then(async (val) => { + if (val) { + // 规则通过静默更新,未通过打开窗口 + const oldInfo = val[1], newScript = val[0]; + if (SystemConfig.silence_update_script && this.checkUpdateRule(oldInfo.metadata, newScript.metadata)) { + // 之前加载的是updateurl的内容,重载downloadurl + const [newScript, oldScript] = await this.controller.prepareScriptByUrl(script.download_url || script.origin); + if (typeof oldScript == 'string') { + App.Log.Error('check update', '更新脚本下载错误', script.name); + return resolve(false); + } + if (!newScript) { + App.Log.Error('check update', '未知错误', script.name); + return resolve(false); + } + void this.scriptReinstall(newScript); + InfoNotification('脚本更新 - ' + oldInfo.name, newScript.name + ' 更新到了 ' + (newScript.metadata['version'] && newScript.metadata['version'][0])) + } else { + const info = await loadScriptByUrl(script.download_url || script.origin); + if (info) { + info.url = script.origin; + info.uuid = uuidv5(info.url, uuidv5.URL) + void App.Cache.set('install:info:' + info.uuid, info); + chrome.tabs.create({ + url: 'install.html?uuid=' + info.uuid, + active: false, + }); + } + } + resolve(true); + } else { + resolve(false); + } + }).catch((e: string) => { + resolve(false); + App.Log.Warn('check update', 'script:' + script.id.toString() + ' error: ' + e, script.name); + }); + } + void handler(); }) } diff --git a/src/pkg/config.ts b/src/pkg/config.ts index 121680a6..25eb67fd 100644 --- a/src/pkg/config.ts +++ b/src/pkg/config.ts @@ -18,7 +18,7 @@ export class SystemConfig { } // 监听设置变化 if (App.Environment === ENV_BACKGROUND) { - MsgCenter.listenerMessage(SYSTEM_CONFIG_CHANGE, (body) => { + MsgCenter.listenerMessage(SYSTEM_CONFIG_CHANGE, (body: { key: string, val: any }) => { this.set(body.key, body.val); this.set('changetime', new Date().getTime()); }); @@ -30,7 +30,7 @@ export class SystemConfig { if (App.Environment === ENV_FRONTEND) { MsgCenter.sendMessage(SYSTEM_CONFIG_CHANGE, { key: key, val: val }); } else { - this.storage.set(key, val); + void this.storage.set(key, val); } } @@ -43,7 +43,7 @@ export class SystemConfig { } public static get changetime() { - return this.cache.get('changetime') || 0; + return this.cache.get('changetime') || 0; } public static set changetime(n: number) { @@ -52,18 +52,25 @@ export class SystemConfig { // 检查更新周期,单位为秒 public static get check_script_update_cycle(): number { - return this.cache.get('check_script_update_cycle') || 86400; + return this.cache.get('check_script_update_cycle') || 86400; } public static set check_script_update_cycle(n: number) { this.set('check_script_update_cycle', n); } + public static get silence_update_script(): boolean { + return this.cache.get('silence_update_script') || false; + } + public static set silence_update_script(val: boolean) { + this.set('silence_update_script', val); + } + public static get enable_auto_sync(): boolean { if (!this.cache.has('enable_auto_sync')) { return true; } - return this.cache.get('enable_auto_sync'); + return this.cache.get('enable_auto_sync'); } public static set enable_auto_sync(enable: boolean) { @@ -71,7 +78,7 @@ export class SystemConfig { } public static get update_disable_script(): boolean { - return this.cache.get('update_disable_script'); + return this.cache.get('update_disable_script'); } public static set update_disable_script(enable: boolean) { @@ -79,7 +86,7 @@ export class SystemConfig { } public static get vscode_url(): string { - return this.cache.get('vscode_url') || 'ws://localhost:8642'; + return this.cache.get('vscode_url') || 'ws://localhost:8642'; } public static set vscode_url(val: string) { @@ -87,7 +94,7 @@ export class SystemConfig { } public static get vscode_reconnect(): boolean { - return this.cache.get('vscode_reconnect') || false; + return this.cache.get('vscode_reconnect') || false; } public static set vscode_reconnect(val: boolean) { diff --git a/src/views/pages/Option/tabs/Config.vue b/src/views/pages/Option/tabs/Config.vue index e7376ffa..879dfef1 100644 --- a/src/views/pages/Option/tabs/Config.vue +++ b/src/views/pages/Option/tabs/Config.vue @@ -66,6 +66,15 @@ export default class Config extends Vue { SystemConfig.check_script_update_cycle = val.value.key; }, }, + { + type: 'check', + value: SystemConfig.silence_update_script, + title: '非重要变更静默更新脚本', + describe: '@connect未发生变化将静默更新脚本', + change(val: any) { + SystemConfig.silence_update_script = val.value; + }, + }, ], }, };