mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 14:34:13 +08:00
825 lines
24 KiB
JavaScript
825 lines
24 KiB
JavaScript
utools.getAppVersion() < "2.6.1" && alert("请升级 uTools 至最新版本");
|
||
// -----------------------------------------------------------------
|
||
const fs = require("fs");
|
||
const os = require("os");
|
||
const child_process = require("child_process");
|
||
const iconv = require("iconv-lite");
|
||
const electron = require("electron");
|
||
const path = require("path");
|
||
const axios = require("axios");
|
||
const http = require("http");
|
||
const url = require("url");
|
||
const kill = require("tree-kill");
|
||
const crypto = require("crypto");
|
||
require("ses");
|
||
const sharp = require("sharp");
|
||
|
||
const md5 = (input) => {
|
||
return crypto.createHash("md5").update(input, "utf8").digest("hex");
|
||
};
|
||
|
||
window._ = require("lodash");
|
||
window.getuToolsLite = require("./lib/utoolsLite");
|
||
// window.yuQueClient = axios.create({
|
||
// baseURL: 'https://www.yuque.com/api/v2/',
|
||
// headers: {
|
||
// 'Content-Type': 'application/json',
|
||
// // 只读权限
|
||
// 'X-Auth-Token': 'WNrd0Z4kfCZLFrGLVAaas93DZ7sbG6PirKq7VxBL'
|
||
// }
|
||
// });
|
||
|
||
window.getSharedQcById = async (id) => {
|
||
const url = "https://qc.qaz.ink/home/quick/script/getScript";
|
||
const timeStamp = parseInt(new Date().getTime() / 1000);
|
||
const { data } = await axios.get(url, {
|
||
params: {
|
||
id,
|
||
},
|
||
headers: {
|
||
"verify-encrypt": md5("quickcommand666" + timeStamp),
|
||
"verify-time": timeStamp,
|
||
},
|
||
});
|
||
return JSON.stringify(data.data);
|
||
};
|
||
|
||
// 检测进程是否存在
|
||
let isProcessExits = (pid) => {
|
||
try {
|
||
return process.kill(pid, 0);
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
window.isAppVersion4 = () => utools.getAppVersion() >= "4.0.0";
|
||
|
||
// 多开检测
|
||
window.multiProcessDetection = () => {
|
||
let pids = JSON.parse(localStorage.getItem("processes")) || [];
|
||
if (pids.length) pids = pids.filter((x) => isProcessExits(x));
|
||
pids.push(process.pid);
|
||
localStorage.setItem("processes", JSON.stringify(pids));
|
||
if (pids.length > 1) return true;
|
||
return false;
|
||
};
|
||
|
||
// axios.defaults.adapter = require('axios/lib/adapters/http')
|
||
|
||
if (!utools.isWindows())
|
||
process.env.PATH = `/usr/local/bin:/usr/local/sbin:${process.env.PATH}`;
|
||
|
||
if (utools.isMacOS())
|
||
process.env.PATH = `/opt/homebrew/bin:/opt/homebrew/sbin:${process.env.PATH}`;
|
||
|
||
const shortCodes = {
|
||
open: (path) => {
|
||
utools.shellOpenItem(path);
|
||
},
|
||
locate: (path) => {
|
||
utools.shellShowItemInFolder(path);
|
||
},
|
||
visit: (url) => {
|
||
utools.shellOpenExternal(url);
|
||
},
|
||
system: (cmd) => {
|
||
let result = child_process.execSync(cmd, {
|
||
windowsHide: true,
|
||
encoding: "buffer",
|
||
});
|
||
return iconv.decode(result, utools.isWindows() ? "gbk" : "utf8");
|
||
},
|
||
message: (msg) => {
|
||
utools.showNotification(msg);
|
||
},
|
||
keyTap: (key, ...modifier) => utools.simulateKeyboardTap(key, ...modifier),
|
||
copyTo: (text) => {
|
||
electron.clipboard.writeText(text);
|
||
},
|
||
send: (text) => {
|
||
utools.hideMainWindowTypeString(text);
|
||
},
|
||
};
|
||
|
||
const ctlKey = utools.isMacOs() ? "command" : "control";
|
||
|
||
window.quickcommand = {
|
||
// 模拟复制操作
|
||
simulateCopy: function () {
|
||
utools.simulateKeyboardTap("c", ctlKey);
|
||
},
|
||
|
||
// 模拟粘贴操作
|
||
simulatePaste: function () {
|
||
utools.simulateKeyboardTap("v", ctlKey);
|
||
},
|
||
|
||
// setTimout 不能在 vm2 中使用,同时在 electron 中有 bug
|
||
sleep: function (ms) {
|
||
var start = new Date().getTime();
|
||
try {
|
||
// node 16.13.1
|
||
child_process.execSync(getSleepCodeByShell(ms), {
|
||
timeout: ms,
|
||
windowsHide: true,
|
||
});
|
||
} catch (ex) {}
|
||
var end = new Date().getTime();
|
||
return end - start;
|
||
},
|
||
|
||
// 重写 setTimeout
|
||
setTimeout: function (callback, ms) {
|
||
var start = new Date().getTime();
|
||
child_process.exec(
|
||
getSleepCodeByShell(ms),
|
||
{
|
||
timeout: ms,
|
||
},
|
||
(err, stdout, stderr) => {
|
||
var end = new Date().getTime();
|
||
callback(end - start);
|
||
}
|
||
);
|
||
},
|
||
|
||
// 关闭进程
|
||
kill: function (pid, signal = "SIGTERM", cb) {
|
||
kill(pid, signal, cb);
|
||
},
|
||
|
||
// dom 解析
|
||
htmlParse: function (html) {
|
||
return new DOMParser().parseFromString(html, "text/html");
|
||
},
|
||
|
||
// 下载文件
|
||
downloadFile: function (url, file = {}) {
|
||
return new Promise((reslove, reject) => {
|
||
if (file instanceof Object)
|
||
file = utools.showSaveDialog(JSON.parse(JSON.stringify(file)));
|
||
axios({
|
||
method: "get",
|
||
url: url,
|
||
responseType: "arraybuffer",
|
||
})
|
||
.then((res) => {
|
||
var filebuffer = Buffer.from(res.data);
|
||
fs.writeFile(file, filebuffer, (err) => {
|
||
if (err) reject(err);
|
||
else reslove(filebuffer);
|
||
});
|
||
})
|
||
.catch((err) => {
|
||
reject(err);
|
||
});
|
||
});
|
||
},
|
||
|
||
// 上传文件
|
||
uploadFile: function (url, file = {}, name = "file", formData = {}) {
|
||
return new Promise((reslove, reject) => {
|
||
var objfile;
|
||
if (file instanceof File) {
|
||
objfile = file;
|
||
} else {
|
||
if (file instanceof Object)
|
||
file = utools.showOpenDialog(JSON.parse(JSON.stringify(file)))[0];
|
||
if (!fs.existsSync(file)) return reject("文件不存在");
|
||
var arraybuffer = fs.readFileSync(file).buffer;
|
||
var objfile = new File([arraybuffer], path.basename(file));
|
||
}
|
||
var form = new FormData();
|
||
form.append(name, objfile);
|
||
var keys = Object.keys(formData);
|
||
if (keys.length) keys.forEach((k) => form.append(k, formData[k]));
|
||
axios
|
||
.post(url, form, {
|
||
headers: {
|
||
accept: "application/json",
|
||
"Content-Type": `multipart/form-data; boundary=${formData._boundary}`,
|
||
},
|
||
})
|
||
.then((res) => {
|
||
reslove(res);
|
||
})
|
||
.catch((err) => {
|
||
reject(err);
|
||
});
|
||
});
|
||
},
|
||
|
||
// 载入在线资源
|
||
loadRemoteScript: async function (url) {
|
||
if (
|
||
!/^((ht|f)tps?):\/\/([\w\-]+(\.[\w\-]+)*\/)*[\w\-]+(\.[\w\-]+)*\/?(\?([\w\-\.,@?^=%&:\/~\+#]*)+)?/.test(
|
||
url
|
||
)
|
||
)
|
||
throw "url 不合法";
|
||
let local = getQuickcommandTempFile("js");
|
||
await this.downloadFile(url, local);
|
||
let source = require(local);
|
||
fs.unlinkSync(local);
|
||
return source;
|
||
},
|
||
|
||
// 唤醒 uTools
|
||
wakeUtools: function () {
|
||
let uToolsPath = utools.isMacOs()
|
||
? process.execPath.replace(/\/Frameworks\/.*/, "/MacOS/uTools")
|
||
: process.execPath;
|
||
child_process.exec(uToolsPath, () => {});
|
||
},
|
||
|
||
readClipboard: function () {
|
||
return electron.clipboard.readText();
|
||
},
|
||
|
||
writeClipboard: function (text) {
|
||
electron.clipboard.writeText(text.toString());
|
||
},
|
||
};
|
||
|
||
if (process.platform === "win32") {
|
||
// 运行vbs脚本
|
||
quickcommand.runVbs = function (script) {
|
||
return new Promise((reslove, reject) => {
|
||
var tempfile = getQuickcommandTempFile("vbs", "TempVBSScript");
|
||
fs.writeFile(tempfile, iconv.encode(script, "gbk"), (err) => {
|
||
child_process.exec(
|
||
`cscript.exe /nologo "${tempfile}"`,
|
||
{
|
||
encoding: "buffer",
|
||
},
|
||
(err, stdout, stderr) => {
|
||
if (err) reject(iconv.decode(stderr, "gbk"));
|
||
else reslove(iconv.decode(stdout, "gbk"));
|
||
}
|
||
);
|
||
});
|
||
});
|
||
};
|
||
// 运行powershell脚本
|
||
quickcommand.runPowerShell = function (script) {
|
||
return new Promise((reslove, reject) => {
|
||
let base64str = Buffer.from(script, "utf16le").toString("base64");
|
||
child_process.exec(
|
||
`powershell.exe -e "${base64str}"`,
|
||
{
|
||
encoding: "buffer",
|
||
},
|
||
(err, stdout, stderr) => {
|
||
if (err) reject(iconv.decode(stderr, "gbk"));
|
||
else reslove(iconv.decode(stdout, "gbk"));
|
||
}
|
||
);
|
||
});
|
||
};
|
||
}
|
||
|
||
if (process.platform === "darwin") {
|
||
// 运行AppleScript脚本
|
||
quickcommand.runAppleScript = function (script) {
|
||
return new Promise((reslove, reject) => {
|
||
child_process.execFile(
|
||
"osascript",
|
||
["-e", script],
|
||
(err, stdout, stderr) => {
|
||
if (err) reject(stderr);
|
||
else reslove(stdout);
|
||
}
|
||
);
|
||
});
|
||
};
|
||
}
|
||
|
||
// python -c
|
||
window.runPythonCommand = (py) => {
|
||
try {
|
||
let result = child_process.execFileSync("python", ["-c", py], {
|
||
windowsHide: true,
|
||
encoding: "buffer",
|
||
});
|
||
return iconv.decode(result, utools.isWindows() ? "gbk" : "utf8").trim();
|
||
} catch (e) {
|
||
alert(e);
|
||
return "";
|
||
}
|
||
};
|
||
|
||
// 在终端中执行
|
||
if (process.platform !== "linux")
|
||
quickcommand.runInTerminal = function (cmdline, dir) {
|
||
let command = getCommandToLaunchTerminal(cmdline, dir);
|
||
child_process.exec(command);
|
||
};
|
||
|
||
let getCommandToLaunchTerminal = (cmdline, dir) => {
|
||
let cd, command;
|
||
if (utools.isWindows()) {
|
||
let appPath = path.join(
|
||
utools.getPath("home"),
|
||
"/AppData/Local/Microsoft/WindowsApps/"
|
||
);
|
||
// 直接 existsSync wt.exe 无效
|
||
if (fs.existsSync(appPath) && fs.readdirSync(appPath).includes("wt.exe")) {
|
||
cmdline = cmdline.replace(/"/g, `\\"`);
|
||
cd = dir ? `-d "${dir.replace(/\\/g, "/")}"` : "";
|
||
command = `${appPath}wt.exe ${cd} cmd /k "${cmdline}"`;
|
||
} else {
|
||
cmdline = cmdline.replace(/"/g, `^"`);
|
||
cd = dir ? `cd /d "${dir.replace(/\\/g, "/")}" &&` : "";
|
||
command = `${cd} start "" cmd /k "${cmdline}"`;
|
||
}
|
||
} else if (utools.isMacOs()) {
|
||
cmdline = cmdline.replace(/"/g, `\\"`);
|
||
cd = dir ? `cd ${dir.replace(/ /g, "\\\\ ")} &&` : "";
|
||
command = fs.existsSync("/Applications/iTerm.app")
|
||
? `osascript -e 'tell application "iTerm"
|
||
if application "iTerm" is running then
|
||
create window with default profile
|
||
end if
|
||
tell current session of first window to write text "clear && ${cd} ${cmdline}"
|
||
activate
|
||
end tell'`
|
||
: `osascript -e 'tell application "Terminal"
|
||
if application "Terminal" is running then
|
||
do script "clear && ${cd} ${cmdline}"
|
||
else
|
||
do script "clear && ${cd} ${cmdline}" in window 1
|
||
end if
|
||
activate
|
||
end tell'`;
|
||
}
|
||
return command;
|
||
};
|
||
|
||
window.pluginInfo = () => {
|
||
return JSON.parse(fs.readFileSync(path.join(__dirname, "plugin.json")));
|
||
};
|
||
|
||
let getSleepCodeByShell = (ms) => {
|
||
var cmd, tempFilePath;
|
||
if (utools.isWindows()) {
|
||
tempFilePath = getQuickcommandTempFile("vbs", "SleepVBSScript");
|
||
cmd = `echo set ws=CreateObject("Wscript.Shell") > ${tempFilePath} && echo Wscript.sleep ${ms} >> ${tempFilePath} && cscript /nologo ${tempFilePath}`;
|
||
} else {
|
||
cmd = `sleep ${ms / 1000}`;
|
||
}
|
||
return cmd;
|
||
};
|
||
|
||
window.htmlEncode = (value) => {
|
||
let dom = quickcommand.htmlParse().querySelector("body");
|
||
dom.innerText = value;
|
||
return dom.innerHTML;
|
||
};
|
||
|
||
window.removeHtmlTags = (value) => {
|
||
return quickcommand.htmlParse(value).querySelector("body").innerText;
|
||
};
|
||
|
||
window.hexEncode = (text) => Buffer.from(text, "utf8").toString("hex");
|
||
window.hexDecode = (text) => Buffer.from(text, "hex").toString("utf8");
|
||
window.base64Decode = (text) => Buffer.from(text, "base64").toString("utf8");
|
||
|
||
window.processPlatform = process.platform;
|
||
window.joinPath = path.join;
|
||
|
||
window.getUtoolsPlugins = () => {
|
||
let root = utools.isMacOs()
|
||
? path.join(os.homedir(), "Library/Application Support/uTools/plugins/")
|
||
: utools.isWindows()
|
||
? path.join(os.homedir(), "AppData/Roaming/uTools/plugins")
|
||
: path.join(os.homedir(), ".config/uTools/plugins");
|
||
let plugins = {};
|
||
let files = fs.readdirSync(root);
|
||
let deleted = path.join(root, "deleted");
|
||
let deletedList = fs.existsSync(deleted)
|
||
? fs.readFileSync(path.join(root, "deleted"), "utf8").split("|")
|
||
: [];
|
||
files.forEach((file) => {
|
||
if (/[a-zA-Z0-9\-]+\.asar$/.test(file) && !deletedList.includes(file)) {
|
||
let pluginInfo = JSON.parse(
|
||
fs.readFileSync(path.join(root, file, "plugin.json"))
|
||
);
|
||
pluginInfo.logoPath = path.join(root, file, pluginInfo.logo);
|
||
let keyWordFeatures = [];
|
||
pluginInfo.features.forEach((f) => {
|
||
f.cmds.some((c) => {
|
||
c.length && keyWordFeatures.push(c);
|
||
return true;
|
||
});
|
||
});
|
||
if (!_.isEmpty(keyWordFeatures)) {
|
||
pluginInfo["keyWordFeatures"] = keyWordFeatures;
|
||
plugins[pluginInfo.pluginName] = pluginInfo;
|
||
}
|
||
}
|
||
});
|
||
return plugins;
|
||
};
|
||
|
||
window.getQuickcommandTempFile = (ext, name, dir = "quickcommandTempDir") => {
|
||
if (!name) name = new Date().getTime() + (Math.random() * 10 ** 6).toFixed();
|
||
let tempDir = path.join(os.tmpdir(), dir);
|
||
if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir);
|
||
return path.join(tempDir, `${name}.${ext}`);
|
||
};
|
||
|
||
window.delTempFile = (...args) => {
|
||
let tmpPath = path.join(os.tmpdir(), ...args);
|
||
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
||
};
|
||
|
||
window.getBase64Ico = (filepath) => {
|
||
let sourceImage,
|
||
ext = path.extname(filepath).slice(1);
|
||
if (["png", "jpg", "jpeg", "bmp", "ico", "gif", "svg"].includes(ext)) {
|
||
if (ext == "svg") ext = "svg+xml";
|
||
sourceImage =
|
||
`data:image/${ext};base64,` + fs.readFileSync(filepath, "base64");
|
||
if (ext == "png") return sourceImage;
|
||
} else {
|
||
sourceImage = utools.getFileIcon(filepath);
|
||
return sourceImage;
|
||
}
|
||
return sourceImage;
|
||
};
|
||
|
||
window.getFileInfo = (options) => {
|
||
var file;
|
||
if (options.type == "file") {
|
||
file = options.argvs;
|
||
} else if (options.type == "dialog") {
|
||
var dialog = utools.showOpenDialog(options.argvs);
|
||
if (!dialog) return false;
|
||
file = dialog[0];
|
||
} else {
|
||
return false;
|
||
}
|
||
var information = {
|
||
name: path.basename(file),
|
||
ext: path.extname(file),
|
||
path: file,
|
||
};
|
||
if (options.readfile) {
|
||
var codec =
|
||
information.ext == ".bat" || information == ".ps1" ? "gbk" : "utf8";
|
||
information.data = iconv.decode(fs.readFileSync(file), codec);
|
||
}
|
||
return information;
|
||
};
|
||
|
||
window.getCurrentFolderPathFix = () => {
|
||
let pwd = utools.getCurrentFolderPath();
|
||
let pwdFix = pwd ? pwd : path.join(utools.getPath("home"), "desktop");
|
||
return pwdFix.replace(/\\/g, "\\\\");
|
||
};
|
||
|
||
window.saveFile = (content, file) => {
|
||
if (file instanceof Object) file = utools.showSaveDialog(file);
|
||
if (!file) return false;
|
||
try {
|
||
fs.writeFileSync(file, content);
|
||
return true;
|
||
} catch (error) {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
window.getSelectFile = (hwnd) => {
|
||
if (utools.isWindows()) {
|
||
var cmd = `powershell.exe -NoProfile "(New-Object -COM 'Shell.Application').Windows() | Where-Object { $_.HWND -eq ${hwnd} } | Select-Object -Expand Document | select @{ n='SelectItems'; e={$_.SelectedItems()} } | select -Expand SelectItems | select -Expand Path "`;
|
||
let result = child_process.execSync(cmd, {
|
||
encoding: "buffer",
|
||
windowsHide: true,
|
||
});
|
||
return iconv.decode(result, "GBK").trim().replace(/\\/g, "/");
|
||
} else {
|
||
var cmd = `osascript -e 'tell application "Finder" to set selectedItems to selection as alias list
|
||
if selectedItems is {} then return
|
||
set parentPath to do shell script "dirname " & quoted form of POSIX path of (item 1 of selectedItems)
|
||
set pathData to ""
|
||
repeat with theItem in selectedItems
|
||
set pathData to pathData & POSIX path of theItem & linefeed
|
||
end repeat
|
||
'
|
||
`;
|
||
let result = child_process.execSync(cmd, {
|
||
encoding: "utf8",
|
||
windowsHide: true,
|
||
});
|
||
return result ? result.trim() : "";
|
||
}
|
||
};
|
||
|
||
let runUbrowser = (path) => {
|
||
utools.ubrowser
|
||
.goto(path)
|
||
.css(
|
||
`
|
||
.ant-modal-content,
|
||
.ant-modal-mask,
|
||
[class*='index-module_contentWrapper'],
|
||
[class*='index-module_reward'],
|
||
[class*='ReaderLayout-module_asideWrapper'],
|
||
[class*='CornerBubble-module_cornerBubble'],
|
||
[class*='DocReader-module_comment'],
|
||
#header,
|
||
#footer {
|
||
display: none
|
||
}`
|
||
)
|
||
.run({
|
||
width: 980,
|
||
height: 750,
|
||
});
|
||
};
|
||
|
||
const docsRepoUrl = "https://www.yuque.com/fofolee/qcdocs3";
|
||
|
||
window.showUb = {
|
||
help: function (path = "") {
|
||
runUbrowser(docsRepoUrl + "/bg31vl" + path);
|
||
},
|
||
docs: function (path = "") {
|
||
runUbrowser(docsRepoUrl + "/pt589p" + path);
|
||
},
|
||
changelog: function (path = "") {
|
||
runUbrowser(docsRepoUrl + "/ucnd2o" + path);
|
||
},
|
||
};
|
||
|
||
window.clipboardReadText = () => electron.clipboard.readText();
|
||
|
||
window.convertFilePathToUtoolsPayload = (files) =>
|
||
files.map((file) => {
|
||
let isFile = fs.statSync(file).isFile();
|
||
return {
|
||
isFile: isFile,
|
||
isDirectory: !isFile,
|
||
name: path.basename(file),
|
||
path: file,
|
||
};
|
||
});
|
||
|
||
let getSandboxFuns = () => {
|
||
var sandbox = {
|
||
fetch: fetch.bind(window),
|
||
utools: getuToolsLite(),
|
||
electron,
|
||
axios,
|
||
Audio,
|
||
_,
|
||
AbortController,
|
||
AbortSignal,
|
||
Buffer,
|
||
require,
|
||
// 兼容老版本
|
||
fs,
|
||
path,
|
||
os,
|
||
child_process,
|
||
};
|
||
Object.keys(shortCodes).forEach((f) => {
|
||
sandbox[f] = shortCodes[f];
|
||
});
|
||
return sandbox;
|
||
};
|
||
|
||
// 简化报错信息
|
||
let liteErr = (e) => {
|
||
if (!e) return;
|
||
return e.error
|
||
? e.error.stack.replace(/([ ] +at.+)|(.+\.js:\d+)/g, "").trim()
|
||
: e.message;
|
||
};
|
||
|
||
// vm 模块将无法在渲染进程中使用,改用 ses 来执行代码
|
||
window.evalCodeInSandbox = (code, addVars = {}) => {
|
||
let sandboxWithAD = Object.assign(addVars, getSandboxFuns());
|
||
sandboxWithAD.quickcommand = _.cloneDeep(quickcommand);
|
||
try {
|
||
return new Compartment(sandboxWithAD).evaluate(code);
|
||
} catch (error) {
|
||
throw liteErr(error);
|
||
}
|
||
};
|
||
|
||
let isWatchingError = false;
|
||
window.runCodeInSandbox = (code, callback, addVars = {}) => {
|
||
let sandbox = getSandboxFuns();
|
||
sandbox.console = {
|
||
log: (...stdout) => {
|
||
console.log("Result:", stdout);
|
||
callback(stdout, null);
|
||
},
|
||
error: (...stderr) => {
|
||
callback(null, stderr);
|
||
},
|
||
};
|
||
let sandboxWithAD = Object.assign(addVars, sandbox);
|
||
sandboxWithAD.quickcommand = _.cloneDeep(quickcommand);
|
||
if (addVars.enterData) {
|
||
sandboxWithAD.quickcommand.enterData = addVars.enterData;
|
||
sandboxWithAD.quickcommand.payload = addVars.enterData.payload;
|
||
}
|
||
try {
|
||
new Compartment(sandboxWithAD).evaluate(code);
|
||
} catch (e) {
|
||
console.log("Error: ", e);
|
||
callback(null, liteErr(e));
|
||
}
|
||
// 自动捕捉错误
|
||
let cbUnhandledError = (e) => {
|
||
removeAllListener();
|
||
console.log("UnhandledError: ", e);
|
||
callback(null, liteErr(e));
|
||
};
|
||
|
||
let cbUnhandledRejection = (e) => {
|
||
removeAllListener();
|
||
console.log("UnhandledRejection: ", e);
|
||
callback(null, liteErr(e.reason));
|
||
};
|
||
|
||
let removeAllListener = () => {
|
||
window.removeEventListener("error", cbUnhandledError);
|
||
window.removeEventListener("unhandledrejection", cbUnhandledRejection);
|
||
isWatchingError = false;
|
||
};
|
||
|
||
if (!isWatchingError) {
|
||
window.addEventListener("error", cbUnhandledError);
|
||
window.addEventListener("unhandledrejection", cbUnhandledRejection);
|
||
isWatchingError = true;
|
||
}
|
||
};
|
||
|
||
window.runCodeFile = (cmd, option, terminal, callback, realTime = true) => {
|
||
let { bin, argv, ext, charset, scptarg, envPath, alias } = option;
|
||
let script = getQuickcommandTempFile(ext, "quickcommandTempScript");
|
||
// 批处理和 powershell 默认编码为 GBK, 解决批处理的换行问题
|
||
if (charset.scriptCode)
|
||
cmd = iconv.encode(cmd.replace(/\n/g, "\r\n"), charset.scriptCode);
|
||
fs.writeFileSync(script, cmd);
|
||
// var argvs = [script]
|
||
// if (argv) {
|
||
// argvs = argv.split(' ')
|
||
// argvs.push(script);
|
||
// }
|
||
let child, cmdline;
|
||
if (bin.slice(-7) == "csc.exe") {
|
||
cmdline = `${bin} ${argv} /out:"${
|
||
script.slice(0, -2) + "exe"
|
||
}" "${script}" && "${script.slice(0, -2) + "exe"}" ${scptarg}`;
|
||
} else if (bin == "gcc") {
|
||
var suffix = utools.isWindows() ? ".exe" : "";
|
||
cmdline = `${bin} ${argv} "${script.slice(0, -2)}" "${script}" && "${
|
||
script.slice(0, -2) + suffix
|
||
}" ${scptarg}`;
|
||
} else if (utools.isWindows() && bin == "bash") {
|
||
cmdline = `${bin} ${argv} "${script
|
||
.replace(/\\/g, "/")
|
||
.replace(/C:/i, "/mnt/c")}" ${scptarg}`;
|
||
} else {
|
||
cmdline = `${bin} ${argv} "${script}" ${scptarg}`;
|
||
}
|
||
let processEnv = _.cloneDeep(process.env);
|
||
if (envPath) processEnv.PATH = envPath;
|
||
if (alias) cmdline = alias + "\n" + cmdline;
|
||
// 在终端中输出
|
||
if (terminal) cmdline = getCommandToLaunchTerminal(cmdline);
|
||
child = child_process.spawn(cmdline, {
|
||
encoding: "buffer",
|
||
shell: true,
|
||
env: processEnv,
|
||
});
|
||
let chunks = [],
|
||
err_chunks = [];
|
||
console.log("Running: " + cmdline);
|
||
child.stdout.on("data", (chunk) => {
|
||
if (charset.outputCode) chunk = iconv.decode(chunk, charset.outputCode);
|
||
realTime ? callback(chunk.toString(), null) : chunks.push(chunk);
|
||
});
|
||
child.stderr.on("data", (err_chunk) => {
|
||
if (charset.outputCode)
|
||
err_chunk = iconv.decode(err_chunk, charset.outputCode);
|
||
realTime
|
||
? callback(null, err_chunk.toString())
|
||
: err_chunks.push(err_chunk);
|
||
});
|
||
if (!realTime) {
|
||
child.on("close", (code) => {
|
||
let stdout = chunks.join("");
|
||
let stderr = err_chunks.join("");
|
||
callback(stdout, stderr);
|
||
});
|
||
}
|
||
return child;
|
||
};
|
||
|
||
const dbStorage = utools.dbStorage;
|
||
let httpServer;
|
||
window.quickcommandHttpServer = () => {
|
||
let run = (port = 33442) => {
|
||
let httpResponse = (res, code, result) => {
|
||
// 只收受一次 console.log,接收后就关闭连接
|
||
if (res.finished) return;
|
||
res.writeHead(code, {
|
||
"Content-Type": "text/html",
|
||
});
|
||
if (result) res.write(result);
|
||
res.end();
|
||
};
|
||
let runUserCode = (res, userVars) => {
|
||
let cmd = dbStorage.getItem("cfg_serverCode");
|
||
// 不需要返回输出的提前关闭连接
|
||
if (!cmd.includes("console.log")) httpResponse(res, 200);
|
||
window.runCodeInSandbox(
|
||
cmd,
|
||
(stdout, stderr) => {
|
||
// 错误返回 500
|
||
if (stderr) return httpResponse(res, 500, stderr.join(" "));
|
||
return httpResponse(res, 200, stdout.join(" "));
|
||
},
|
||
userVars
|
||
);
|
||
};
|
||
httpServer = http.createServer();
|
||
httpServer.on("request", (req, res) => {
|
||
if (req.method === "GET") {
|
||
let parsedParams = _.cloneDeep(url.parse(req.url, true).query);
|
||
runUserCode(res, parsedParams);
|
||
} else if (req.method === "POST") {
|
||
let data = [];
|
||
req.on("data", (chunk) => {
|
||
data.push(chunk);
|
||
});
|
||
req.on("end", () => {
|
||
let parsedParams;
|
||
let params = data.join("").toString();
|
||
// 先尝试作为 json 解析
|
||
try {
|
||
parsedParams = JSON.parse(params);
|
||
} catch (error) {
|
||
parsedParams = _.cloneDeep(url.parse("?" + params, true).query);
|
||
}
|
||
runUserCode(res, parsedParams);
|
||
});
|
||
} else {
|
||
httpResponse(res, 405);
|
||
}
|
||
});
|
||
httpServer.listen(port, "localhost");
|
||
httpServer.on("error", (err) => {
|
||
utools.showNotification("快捷命令服务:", err);
|
||
});
|
||
};
|
||
let stop = () => {
|
||
if (!httpServer) return;
|
||
httpServer.close();
|
||
};
|
||
return {
|
||
run,
|
||
stop,
|
||
};
|
||
};
|
||
|
||
// 处理背景图片
|
||
window.imageProcessor = async (imagePath) => {
|
||
try {
|
||
// 读取图片
|
||
let image = sharp(imagePath);
|
||
let metadata = await image.metadata();
|
||
|
||
// 设置固定目标尺寸
|
||
let targetWidth = 1280;
|
||
let targetHeight = 720;
|
||
const ratio = metadata.width / metadata.height;
|
||
|
||
if (ratio > 16 / 9) {
|
||
targetHeight = Math.min(720, Math.round(targetWidth / ratio));
|
||
} else {
|
||
targetWidth = Math.min(1280, Math.round(targetHeight * ratio));
|
||
}
|
||
|
||
// 调整大小并压缩
|
||
let processedBuffer = await image
|
||
.resize(targetWidth, targetHeight, {
|
||
fit: "contain",
|
||
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
||
})
|
||
.jpeg({ quality: 80, progressive: true })
|
||
.toBuffer();
|
||
|
||
return `data:image/jpeg;base64,${processedBuffer.toString("base64")}`;
|
||
} catch (error) {
|
||
console.error("处理图片失败:", error);
|
||
return null;
|
||
}
|
||
};
|