CAT API
This commit is contained in:
parent
071e728f06
commit
1a531dfad5
@ -1,5 +1,6 @@
|
|||||||
import { ExtServer, ExtServerApi } from "@App/app/const";
|
import { ExtServer, ExtServerApi } from "@App/app/const";
|
||||||
import { WarpTokenError } from "./error";
|
import { WarpTokenError } from "./error";
|
||||||
|
import { LocalStorageDAO } from "@App/app/repo/localStorage";
|
||||||
|
|
||||||
type NetDiskType = "baidu" | "onedrive";
|
type NetDiskType = "baidu" | "onedrive";
|
||||||
|
|
||||||
@ -8,11 +9,7 @@ export function GetNetDiskToken(netDiskType: NetDiskType): Promise<{
|
|||||||
msg: string;
|
msg: string;
|
||||||
data: { token: { access_token: string; refresh_token: string } };
|
data: { token: { access_token: string; refresh_token: string } };
|
||||||
}> {
|
}> {
|
||||||
return fetch(ExtServerApi + `auth/net-disk/token?netDiskType=${netDiskType}`)
|
return fetch(ExtServerApi + `auth/net-disk/token?netDiskType=${netDiskType}`).then((resp) => resp.json());
|
||||||
.then((resp) => resp.json())
|
|
||||||
.then((resp) => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RefreshToken(
|
export function RefreshToken(
|
||||||
@ -32,27 +29,45 @@ export function RefreshToken(
|
|||||||
netDiskType,
|
netDiskType,
|
||||||
refreshToken,
|
refreshToken,
|
||||||
}),
|
}),
|
||||||
})
|
}).then((resp) => resp.json());
|
||||||
.then((resp) => resp.json())
|
|
||||||
.then((resp) => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NetDisk(netDiskType: NetDiskType) {
|
export function NetDisk(netDiskType: NetDiskType) {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
const loginWindow = window.open(`${ExtServer}api/v1/auth/net-disk?netDiskType=${netDiskType}`);
|
if (globalThis.window) {
|
||||||
const t = setInterval(() => {
|
const loginWindow = window.open(`${ExtServer}api/v1/auth/net-disk?netDiskType=${netDiskType}`);
|
||||||
try {
|
const t = setInterval(() => {
|
||||||
if (loginWindow!.closed) {
|
try {
|
||||||
|
if (loginWindow!.closed) {
|
||||||
|
clearInterval(t);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
clearInterval(t);
|
clearInterval(t);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
}, 1000);
|
||||||
clearInterval(t);
|
} else {
|
||||||
resolve();
|
chrome.tabs
|
||||||
}
|
.create({
|
||||||
}, 1000);
|
url: `${ExtServer}api/v1/auth/net-disk?netDiskType=${netDiskType}`,
|
||||||
|
})
|
||||||
|
.then(({ id: tabId }) => {
|
||||||
|
const t = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const tab = await chrome.tabs.get(tabId!);
|
||||||
|
console.log("query tab", tab);
|
||||||
|
if (!tab) {
|
||||||
|
clearInterval(t);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
clearInterval(t);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +79,15 @@ export type Token = {
|
|||||||
|
|
||||||
export async function AuthVerify(netDiskType: NetDiskType, invalid?: boolean) {
|
export async function AuthVerify(netDiskType: NetDiskType, invalid?: boolean) {
|
||||||
let token: Token | undefined;
|
let token: Token | undefined;
|
||||||
|
const localStorageDao = new LocalStorageDAO();
|
||||||
|
const key = `netdisk:token:${netDiskType}`;
|
||||||
try {
|
try {
|
||||||
token = JSON.parse(localStorage[`netdisk:token:${netDiskType}`]);
|
token = await localStorageDao.get(key).then((resp) => {
|
||||||
|
if (resp) {
|
||||||
|
return resp.value;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
@ -83,7 +105,10 @@ export async function AuthVerify(netDiskType: NetDiskType, invalid?: boolean) {
|
|||||||
createtime: Date.now(),
|
createtime: Date.now(),
|
||||||
};
|
};
|
||||||
invalid = false;
|
invalid = false;
|
||||||
localStorage[`netdisk:token:${netDiskType}`] = JSON.stringify(token);
|
await localStorageDao.save({
|
||||||
|
key,
|
||||||
|
value: token,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// token过期或者失效
|
// token过期或者失效
|
||||||
if (Date.now() >= token.createtime + 3600000 || invalid) {
|
if (Date.now() >= token.createtime + 3600000 || invalid) {
|
||||||
@ -91,7 +116,7 @@ export async function AuthVerify(netDiskType: NetDiskType, invalid?: boolean) {
|
|||||||
try {
|
try {
|
||||||
const resp = await RefreshToken(netDiskType, token.refreshToken);
|
const resp = await RefreshToken(netDiskType, token.refreshToken);
|
||||||
if (resp.code !== 0) {
|
if (resp.code !== 0) {
|
||||||
localStorage.removeItem(`netdisk:token:${netDiskType}`);
|
await localStorageDao.delete(key);
|
||||||
// 刷新失败,并且标记失效,尝试重新获取token
|
// 刷新失败,并且标记失效,尝试重新获取token
|
||||||
if (invalid) {
|
if (invalid) {
|
||||||
return AuthVerify(netDiskType);
|
return AuthVerify(netDiskType);
|
||||||
@ -103,7 +128,11 @@ export async function AuthVerify(netDiskType: NetDiskType, invalid?: boolean) {
|
|||||||
refreshToken: resp.data.token.refresh_token,
|
refreshToken: resp.data.token.refresh_token,
|
||||||
createtime: Date.now(),
|
createtime: Date.now(),
|
||||||
};
|
};
|
||||||
localStorage[`netdisk:token:${netDiskType}`] = JSON.stringify(token);
|
// 更新token
|
||||||
|
await localStorageDao.save({
|
||||||
|
key,
|
||||||
|
value: token,
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 报错返回原token
|
// 报错返回原token
|
||||||
return Promise.resolve(token.accessToken);
|
return Promise.resolve(token.accessToken);
|
||||||
|
@ -55,12 +55,11 @@ export default class BaiduFileSystem implements FileSystem {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
async request(url: string, config?: RequestInit) {
|
||||||
request(url: string, config?: RequestInit) {
|
|
||||||
config = config || {};
|
config = config || {};
|
||||||
const headers = <Headers>config.headers || new Headers();
|
const headers = <Headers>config.headers || new Headers();
|
||||||
// 处理请求匿名不发送cookie
|
// 处理请求匿名不发送cookie
|
||||||
chrome.declarativeNetRequest.updateDynamicRules({
|
await chrome.declarativeNetRequest.updateDynamicRules({
|
||||||
removeRuleIds: [100],
|
removeRuleIds: [100],
|
||||||
addRules: [
|
addRules: [
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable max-classes-per-file */
|
|
||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
import { calculateMd5 } from "@App/pkg/utils/utils";
|
import { calculateMd5 } from "@App/pkg/utils/utils";
|
||||||
import { MD5 } from "crypto-js";
|
import { MD5 } from "crypto-js";
|
||||||
import { File, FileReader, FileWriter } from "../filesystem";
|
import { File, FileReader, FileWriter } from "../filesystem";
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// eslint-disable-next-line import/prefer-default-export, max-classes-per-file
|
|
||||||
export class WarpTokenError {
|
export class WarpTokenError {
|
||||||
error: Error;
|
error: Error;
|
||||||
|
|
||||||
|
17
src/app/repo/localStorage.ts
Normal file
17
src/app/repo/localStorage.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Repo } from "./repo";
|
||||||
|
|
||||||
|
export interface LocalStorageItem {
|
||||||
|
key: string;
|
||||||
|
value: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 由于service worker不能使用localStorage,这里新建一个类来实现localStorage的功能
|
||||||
|
export class LocalStorageDAO extends Repo<LocalStorageItem> {
|
||||||
|
constructor() {
|
||||||
|
super("localStorage");
|
||||||
|
}
|
||||||
|
|
||||||
|
save(value: LocalStorageItem) {
|
||||||
|
return super._save(value.key, value);
|
||||||
|
}
|
||||||
|
}
|
@ -318,6 +318,52 @@ export default class GMApi {
|
|||||||
this.sendMessage("GM_unregisterMenuCommand", [id]);
|
this.sendMessage("GM_unregisterMenuCommand", [id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GMContext.API()
|
||||||
|
CAT_userConfig() {
|
||||||
|
return this.sendMessage("CAT_userConfig", []);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GMContext.API({
|
||||||
|
depend: ["CAT_fetchBlob", "CAT_createBlobUrl"],
|
||||||
|
})
|
||||||
|
async CAT_fileStorage(action: "list" | "download" | "upload" | "delete" | "config", details: any) {
|
||||||
|
if (action === "config") {
|
||||||
|
this.sendMessage("CAT_fileStorage", ["config"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sendDetails: { [key: string]: string } = {
|
||||||
|
baseDir: details.baseDir || "",
|
||||||
|
path: details.path || "",
|
||||||
|
filename: details.filename,
|
||||||
|
file: details.file,
|
||||||
|
};
|
||||||
|
if (action === "upload") {
|
||||||
|
const url = await this.CAT_createBlobUrl(details.data);
|
||||||
|
sendDetails.data = url;
|
||||||
|
}
|
||||||
|
this.sendMessage("CAT_fileStorage", [action, sendDetails]).then(async (resp: { action: string; data: any }) => {
|
||||||
|
switch (resp.action) {
|
||||||
|
case "onload": {
|
||||||
|
if (action === "download") {
|
||||||
|
// 读取blob
|
||||||
|
const blob = await this.CAT_fetchBlob(resp.data);
|
||||||
|
details.onload && details.onload(blob);
|
||||||
|
} else {
|
||||||
|
details.onload && details.onload(resp.data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "error": {
|
||||||
|
if (typeof resp.data.code === "undefined") {
|
||||||
|
details.onerror && details.onerror({ code: -1, message: resp.data.message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
details.onerror && details.onerror(resp.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 用于脚本跨域请求,需要@connect domain指定允许的域名
|
// 用于脚本跨域请求,需要@connect domain指定允许的域名
|
||||||
@GMContext.API({
|
@GMContext.API({
|
||||||
depend: ["CAT_fetchBlob", "CAT_createBlobUrl", "CAT_fetchDocument"],
|
depend: ["CAT_fetchBlob", "CAT_createBlobUrl", "CAT_fetchDocument"],
|
||||||
|
@ -10,10 +10,13 @@ import EventEmitter from "eventemitter3";
|
|||||||
import { MessageQueue } from "@Packages/message/message_queue";
|
import { MessageQueue } from "@Packages/message/message_queue";
|
||||||
import { RuntimeService } from "./runtime";
|
import { RuntimeService } from "./runtime";
|
||||||
import { getIcon, isFirefox } from "@App/pkg/utils/utils";
|
import { getIcon, isFirefox } from "@App/pkg/utils/utils";
|
||||||
import { PopupService } from "./popup";
|
|
||||||
import { act } from "react";
|
|
||||||
import { MockMessageConnect } from "@Packages/message/mock_message";
|
import { MockMessageConnect } from "@Packages/message/mock_message";
|
||||||
import i18next, { i18nName } from "@App/locales/locales";
|
import i18next, { i18nName } from "@App/locales/locales";
|
||||||
|
import { SystemConfig } from "@App/pkg/config/config";
|
||||||
|
import FileSystemFactory from "@Packages/filesystem/factory";
|
||||||
|
import FileSystem from "@Packages/filesystem/filesystem";
|
||||||
|
import { isWarpTokenError } from "@Packages/filesystem/error";
|
||||||
|
import { joinPath } from "@Packages/filesystem/utils";
|
||||||
|
|
||||||
// GMApi,处理脚本的GM API调用请求
|
// GMApi,处理脚本的GM API调用请求
|
||||||
|
|
||||||
@ -71,6 +74,7 @@ export default class GMApi {
|
|||||||
scriptDAO: ScriptDAO = new ScriptDAO();
|
scriptDAO: ScriptDAO = new ScriptDAO();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private systemConfig: SystemConfig,
|
||||||
private permissionVerify: PermissionVerify,
|
private permissionVerify: PermissionVerify,
|
||||||
private group: Group,
|
private group: Group,
|
||||||
private send: MessageSend,
|
private send: MessageSend,
|
||||||
@ -248,6 +252,119 @@ export default class GMApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PermissionVerify.API()
|
||||||
|
CAT_userConfig(request: Request) {
|
||||||
|
chrome.tabs.create({
|
||||||
|
url: `/src/options.html#/?userConfig=${request.uuid}`,
|
||||||
|
active: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@PermissionVerify.API({
|
||||||
|
confirm: (request: Request) => {
|
||||||
|
const [action, details] = request.params;
|
||||||
|
if (action === "config") {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
const dir = details.baseDir ? details.baseDir : request.script.uuid;
|
||||||
|
const metadata: { [key: string]: string } = {};
|
||||||
|
metadata[i18next.t("script_name")] = i18nName(request.script);
|
||||||
|
return Promise.resolve({
|
||||||
|
permission: "file_storage",
|
||||||
|
permissionValue: dir,
|
||||||
|
title: i18next.t("script_operation_title"),
|
||||||
|
metadata,
|
||||||
|
describe: i18next.t("script_operation_description", { dir }),
|
||||||
|
wildcard: false,
|
||||||
|
permissionContent: i18next.t("script_permission_content"),
|
||||||
|
} as ConfirmParam);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
async CAT_fileStorage(request: Request, sender: GetSender): Promise<{ action: string; data: any } | boolean> {
|
||||||
|
const [action, details] = request.params;
|
||||||
|
if (action === "config") {
|
||||||
|
chrome.tabs.create({
|
||||||
|
url: `/src/options.html#/setting`,
|
||||||
|
active: true,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const fsConfig = await this.systemConfig.getCatFileStorage();
|
||||||
|
if (fsConfig.status === "unset") {
|
||||||
|
return { action: "error", data: { code: 1, error: "file storage is unset" } };
|
||||||
|
}
|
||||||
|
if (fsConfig.status === "error") {
|
||||||
|
return { action: "error", data: { code: 2, error: "file storage is error" } };
|
||||||
|
}
|
||||||
|
let fs: FileSystem;
|
||||||
|
const baseDir = `ScriptCat/app/${details.baseDir ? details.baseDir : request.script.uuid}`;
|
||||||
|
try {
|
||||||
|
fs = await FileSystemFactory.create(fsConfig.filesystem, fsConfig.params[fsConfig.filesystem]);
|
||||||
|
await FileSystemFactory.mkdirAll(fs, baseDir);
|
||||||
|
fs = await fs.openDir(baseDir);
|
||||||
|
} catch (e: any) {
|
||||||
|
if (isWarpTokenError(e)) {
|
||||||
|
fsConfig.status = "error";
|
||||||
|
this.systemConfig.setCatFileStorage(fsConfig);
|
||||||
|
return { action: "error", data: { code: 2, error: e.error.message } };
|
||||||
|
}
|
||||||
|
return { action: "error", data: { code: 8, error: e.message } };
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
|
case "list":
|
||||||
|
try {
|
||||||
|
const list = await fs.list();
|
||||||
|
list.forEach((file) => {
|
||||||
|
(<any>file).absPath = file.path;
|
||||||
|
file.path = joinPath(file.path.substring(file.path.indexOf(baseDir) + baseDir.length));
|
||||||
|
});
|
||||||
|
return { action: "onload", data: list };
|
||||||
|
} catch (e: any) {
|
||||||
|
return { action: "error", data: { code: 3, error: e.message } };
|
||||||
|
}
|
||||||
|
case "upload":
|
||||||
|
try {
|
||||||
|
const w = await fs.create(details.path);
|
||||||
|
await w.write(await (await fetch(<string>details.data)).blob());
|
||||||
|
return { action: "onload", data: true };
|
||||||
|
} catch (e: any) {
|
||||||
|
return { action: "error", data: { code: 4, error: e.message } };
|
||||||
|
}
|
||||||
|
case "download":
|
||||||
|
try {
|
||||||
|
const info = <CATType.FileStorageFileInfo>details.file;
|
||||||
|
fs = await fs.openDir(`${info.path}`);
|
||||||
|
const r = await fs.open({
|
||||||
|
fsid: (<any>info).fsid,
|
||||||
|
name: info.name,
|
||||||
|
path: info.absPath,
|
||||||
|
size: info.size,
|
||||||
|
digest: info.digest,
|
||||||
|
createtime: info.createtime,
|
||||||
|
updatetime: info.updatetime,
|
||||||
|
});
|
||||||
|
const blob = await r.read("blob");
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
setTimeout(() => {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}, 6000);
|
||||||
|
return { action: "onload", data: url };
|
||||||
|
} catch (e: any) {
|
||||||
|
return { action: "error", data: { code: 5, error: e.message } };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
try {
|
||||||
|
await fs.delete(`${details.path}`);
|
||||||
|
return { action: "onload", data: true };
|
||||||
|
} catch (e: any) {
|
||||||
|
return { action: "error", data: { code: 6, error: e.message } };
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error("action is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 根据header生成dnr规则
|
// 根据header生成dnr规则
|
||||||
async buildDNRRule(reqeustId: number, params: GMSend.XHRDetails): Promise<{ [key: string]: string }> {
|
async buildDNRRule(reqeustId: number, params: GMSend.XHRDetails): Promise<{ [key: string]: string }> {
|
||||||
// 检查是否有unsafe header,有则生成dnr规则
|
// 检查是否有unsafe header,有则生成dnr规则
|
||||||
@ -401,7 +518,6 @@ export default class GMApi {
|
|||||||
|
|
||||||
@PermissionVerify.API({
|
@PermissionVerify.API({
|
||||||
confirm: async (request: Request) => {
|
confirm: async (request: Request) => {
|
||||||
console.log("confirm", request);
|
|
||||||
const config = <GMSend.XHRDetails>request.params[0];
|
const config = <GMSend.XHRDetails>request.params[0];
|
||||||
const url = new URL(config.url);
|
const url = new URL(config.url);
|
||||||
if (request.script.metadata.connect) {
|
if (request.script.metadata.connect) {
|
||||||
|
@ -6,6 +6,7 @@ import { ValueService } from "./value";
|
|||||||
import { RuntimeService } from "./runtime";
|
import { RuntimeService } from "./runtime";
|
||||||
import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
|
import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
|
||||||
import { PopupService } from "./popup";
|
import { PopupService } from "./popup";
|
||||||
|
import { SystemConfig } from "@App/pkg/config/config";
|
||||||
|
|
||||||
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
||||||
|
|
||||||
@ -24,12 +25,14 @@ export default class ServiceWorkerManager {
|
|||||||
this.mq.emit("preparationOffscreen", {});
|
this.mq.emit("preparationOffscreen", {});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const systemConfig = new SystemConfig(this.mq);
|
||||||
|
|
||||||
const resource = new ResourceService(this.api.group("resource"), this.mq);
|
const resource = new ResourceService(this.api.group("resource"), this.mq);
|
||||||
resource.init();
|
resource.init();
|
||||||
const value = new ValueService(this.api.group("value"), this.sender);
|
const value = new ValueService(this.api.group("value"), this.sender);
|
||||||
const script = new ScriptService(this.api.group("script"), this.mq, value, resource);
|
const script = new ScriptService(this.api.group("script"), this.mq, value, resource);
|
||||||
script.init();
|
script.init();
|
||||||
const runtime = new RuntimeService(this.api.group("runtime"), this.sender, this.mq, value, script);
|
const runtime = new RuntimeService(systemConfig, this.api.group("runtime"), this.sender, this.mq, value, script);
|
||||||
runtime.init();
|
runtime.init();
|
||||||
const popup = new PopupService(this.api.group("popup"), this.mq, runtime);
|
const popup = new PopupService(this.api.group("popup"), this.mq, runtime);
|
||||||
popup.init();
|
popup.init();
|
||||||
|
@ -181,7 +181,6 @@ export default class PermissionVerify {
|
|||||||
}
|
}
|
||||||
return Promise.resolve(model);
|
return Promise.resolve(model);
|
||||||
});
|
});
|
||||||
console.log("confirm", request, confirm);
|
|
||||||
// 有查询到结果,进入判断,不再需要用户确认
|
// 有查询到结果,进入判断,不再需要用户确认
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret.allow) {
|
if (ret.allow) {
|
||||||
|
@ -25,6 +25,7 @@ import { PopupService } from "./popup";
|
|||||||
import Logger from "@App/app/logger/logger";
|
import Logger from "@App/app/logger/logger";
|
||||||
import LoggerCore from "@App/app/logger/core";
|
import LoggerCore from "@App/app/logger/core";
|
||||||
import PermissionVerify from "./permission_verify";
|
import PermissionVerify from "./permission_verify";
|
||||||
|
import { SystemConfig } from "@App/pkg/config/config";
|
||||||
|
|
||||||
// 为了优化性能,存储到缓存时删除了code与value
|
// 为了优化性能,存储到缓存时删除了code与value
|
||||||
export interface ScriptMatchInfo extends ScriptRunResouce {
|
export interface ScriptMatchInfo extends ScriptRunResouce {
|
||||||
@ -48,6 +49,7 @@ export class RuntimeService {
|
|||||||
scriptMatchCache: Map<string, ScriptMatchInfo> | null | undefined;
|
scriptMatchCache: Map<string, ScriptMatchInfo> | null | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private systemConfig: SystemConfig,
|
||||||
private group: Group,
|
private group: Group,
|
||||||
private sender: MessageSend,
|
private sender: MessageSend,
|
||||||
private mq: MessageQueue,
|
private mq: MessageQueue,
|
||||||
@ -58,7 +60,7 @@ export class RuntimeService {
|
|||||||
async init() {
|
async init() {
|
||||||
// 启动gm api
|
// 启动gm api
|
||||||
const permission = new PermissionVerify(this.group.group("permission"));
|
const permission = new PermissionVerify(this.group.group("permission"));
|
||||||
const gmApi = new GMApi(permission, this.group, this.sender, this.mq, this.value, this);
|
const gmApi = new GMApi(this.systemConfig, permission, this.group, this.sender, this.mq, this.value, this);
|
||||||
permission.init();
|
permission.init();
|
||||||
gmApi.start();
|
gmApi.start();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Metadata, Script } from "@App/app/repo/scripts";
|
import { Metadata, Script } from "@App/app/repo/scripts";
|
||||||
import { CronTime } from "cron";
|
import { CronTime } from "cron";
|
||||||
|
import crypto from "crypto-js";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import semver from "semver";
|
import semver from "semver";
|
||||||
|
|
||||||
@ -234,3 +235,18 @@ export function getIcon(script: Script): string | undefined {
|
|||||||
(script.metadata.icon64url && script.metadata.icon64url[0])
|
(script.metadata.icon64url && script.metadata.icon64url[0])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function calculateMd5(blob: Blob) {
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsArrayBuffer(blob);
|
||||||
|
reader.onloadend = () => {
|
||||||
|
if (!reader.result) {
|
||||||
|
reject(new Error("result is null"));
|
||||||
|
} else {
|
||||||
|
const wordArray = crypto.lib.WordArray.create(<ArrayBuffer>reader.result);
|
||||||
|
resolve(crypto.MD5(wordArray).toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user