2022-06-17 15:10:02 +08:00
|
|
|
|
import lodash from "lodash";
|
|
|
|
|
import fs from "fs";
|
2022-10-17 20:55:39 +08:00
|
|
|
|
import { pipeline } from 'stream'
|
|
|
|
|
import { promisify } from 'util'
|
|
|
|
|
import fetch from 'node-fetch'
|
|
|
|
|
import path from 'node:path'
|
2022-07-24 11:46:05 +08:00
|
|
|
|
const _path = process.cwd()
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
|
|
|
|
let Data = {
|
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
/*
|
|
|
|
|
* 根据指定的path依次检查与创建目录
|
|
|
|
|
* */
|
|
|
|
|
createDir(rootPath = "", path = "", includeFile = false) {
|
|
|
|
|
let pathList = path.split("/"),
|
|
|
|
|
nowPath = rootPath;
|
|
|
|
|
pathList.forEach((name, idx) => {
|
|
|
|
|
name = name.trim();
|
|
|
|
|
if (!includeFile && idx <= pathList.length - 1) {
|
|
|
|
|
nowPath += name + "/";
|
|
|
|
|
if (name) {
|
|
|
|
|
if (!fs.existsSync(nowPath)) {
|
|
|
|
|
fs.mkdirSync(nowPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 读取json
|
|
|
|
|
* */
|
|
|
|
|
readJSON(root, path) {
|
|
|
|
|
if (!/\.json$/.test(path)) {
|
|
|
|
|
path = path + ".json";
|
|
|
|
|
}
|
|
|
|
|
// 检查并创建目录
|
|
|
|
|
Data.createDir(root, path, true);
|
|
|
|
|
if (fs.existsSync(`${root}/${path}`)) {
|
|
|
|
|
let jsonRet = fs.readFileSync(`${root}/${path}`, "utf8");
|
|
|
|
|
return JSON.parse(jsonRet);
|
|
|
|
|
}
|
|
|
|
|
return {}
|
|
|
|
|
},
|
|
|
|
|
mkdirs (dirname) {
|
|
|
|
|
if (fs.existsSync(dirname)) {
|
|
|
|
|
return true
|
|
|
|
|
} else {
|
|
|
|
|
if (Data.mkdirs(path.dirname(dirname))) {
|
|
|
|
|
fs.mkdirSync(dirname)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* 下载保存文件
|
|
|
|
|
* @param fileUrl 下载地址
|
|
|
|
|
* @param savePath 保存路径
|
|
|
|
|
*/
|
|
|
|
|
async downFile(fileUrl, savePath, param = {}) {
|
|
|
|
|
try {
|
|
|
|
|
Data.mkdirs(path.dirname(savePath))
|
|
|
|
|
Bot.logger.mark(`[下载文件] ${fileUrl}`)
|
|
|
|
|
const response = await fetch(fileUrl, param)
|
|
|
|
|
const streamPipeline = promisify(pipeline)
|
|
|
|
|
await streamPipeline(response.body, fs.createWriteStream(savePath))
|
|
|
|
|
return true
|
|
|
|
|
} catch (err) {
|
|
|
|
|
Bot.logger.error(`下载文件错误:${err}`)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
/*
|
|
|
|
|
* 写JSON
|
|
|
|
|
* */
|
|
|
|
|
writeJson(root, path, file, data, space = "\t") {
|
|
|
|
|
if (!/\.json$/.test(file)) {
|
|
|
|
|
file = file + ".json";
|
|
|
|
|
}
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
// 检查并创建目录
|
|
|
|
|
Data.createDir(path, true);
|
|
|
|
|
return fs.writeFileSync(`${path}/${file}`, JSON.stringify(data, null, space));
|
|
|
|
|
},
|
|
|
|
|
async importModule(path, file, rootPath = _path) {
|
|
|
|
|
if (!/\.js$/.test(file)) {
|
|
|
|
|
file = file + '.js'
|
|
|
|
|
}
|
|
|
|
|
// 检查并创建目录
|
|
|
|
|
Data.createDir(_path, path, true)
|
|
|
|
|
if (fs.existsSync(`${_path}/${path}/${file}`)) {
|
|
|
|
|
let data = await import(`file://${_path}/${path}/${file}`)
|
|
|
|
|
return data || {}
|
|
|
|
|
}
|
|
|
|
|
return {}
|
|
|
|
|
},
|
|
|
|
|
/*
|
|
|
|
|
* 返回一个从 target 中选中的属性的对象
|
|
|
|
|
*
|
|
|
|
|
* keyList : 获取字段列表,逗号分割字符串
|
|
|
|
|
* key1, key2, toKey1:fromKey1, toKey2:fromObj.key
|
|
|
|
|
*
|
|
|
|
|
* defaultData: 当某个字段为空时会选取defaultData的对应内容
|
|
|
|
|
* toKeyPrefix:返回数据的字段前缀,默认为空。defaultData中的键值无需包含toKeyPrefix
|
|
|
|
|
*
|
|
|
|
|
* */
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
getData(target, keyList = "", cfg = {}) {
|
|
|
|
|
target = target || {};
|
|
|
|
|
let defaultData = cfg.defaultData || {};
|
|
|
|
|
let ret = {};
|
|
|
|
|
// 分割逗号
|
|
|
|
|
if (typeof(keyList) === "string") {
|
|
|
|
|
keyList = keyList.split(",");
|
|
|
|
|
}
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
lodash.forEach(keyList, (keyCfg) => {
|
|
|
|
|
// 处理通过:指定 toKey & fromKey
|
|
|
|
|
let _keyCfg = keyCfg.split(":");
|
|
|
|
|
let keyTo = _keyCfg[0].trim(),
|
|
|
|
|
keyFrom = (_keyCfg[1] || _keyCfg[0]).trim(),
|
|
|
|
|
keyRet = keyTo;
|
|
|
|
|
if (cfg.lowerFirstKey) {
|
|
|
|
|
keyRet = lodash.lowerFirst(keyRet);
|
|
|
|
|
}
|
|
|
|
|
if (cfg.keyPrefix) {
|
|
|
|
|
keyRet = cfg.keyPrefix + keyRet;
|
|
|
|
|
}
|
|
|
|
|
// 通过Data.getVal获取数据
|
|
|
|
|
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg);
|
|
|
|
|
})
|
|
|
|
|
return ret;
|
|
|
|
|
},
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
getVal(target, keyFrom, defaultValue) {
|
|
|
|
|
return lodash.get(target, keyFrom, defaultValue);
|
|
|
|
|
},
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
getUrlPath(url) {
|
|
|
|
|
let reg = /^https*:\/\/(.*)\/(\w+\.(png|jpg|jpeg|webp))(\?.*)?$/;
|
|
|
|
|
let ret = reg.exec(url);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
path: ret[1],
|
|
|
|
|
filename: ret[2],
|
|
|
|
|
type: ret[3],
|
|
|
|
|
url
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
pathExists(root, path) {
|
|
|
|
|
if (fs.existsSync(root + "/" + path)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
path = path.replace("\\", "/");
|
|
|
|
|
const dirList = path.split("/");
|
|
|
|
|
let currentDir = root;
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
for (let dir of dirList) {
|
|
|
|
|
currentDir = currentDir + "/" + dir;
|
|
|
|
|
if (!fs.existsSync(currentDir)) {
|
|
|
|
|
fs.mkdirSync(currentDir);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
async asyncPool(poolLimit, array, iteratorFn) {
|
|
|
|
|
const ret = []; // 存储所有的异步任务
|
|
|
|
|
const executing = []; // 存储正在执行的异步任务
|
|
|
|
|
for (const item of array) {
|
|
|
|
|
// 调用iteratorFn函数创建异步任务
|
|
|
|
|
const p = Promise.resolve().then(() => iteratorFn(item, array));
|
|
|
|
|
// 保存新的异步任务
|
|
|
|
|
ret.push(p);
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
// 当poolLimit值小于或等于总任务个数时,进行并发控制
|
|
|
|
|
if (poolLimit <= array.length) {
|
|
|
|
|
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
|
|
|
|
|
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
|
|
|
|
|
executing.push(e); // 保存正在执行的异步任务
|
|
|
|
|
if (executing.length >= poolLimit) {
|
|
|
|
|
// 等待较快的任务执行完成
|
|
|
|
|
await Promise.race(executing);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Promise.all(ret);
|
|
|
|
|
},
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
2022-10-17 20:55:39 +08:00
|
|
|
|
sleep(ms) {
|
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
|
}
|
2022-06-17 15:10:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Data;
|