2022-07-23 20:32:10 +00:00
|
|
|
|
import lodash from 'lodash'
|
|
|
|
|
import fs from 'fs'
|
2022-03-26 08:21:44 +00:00
|
|
|
|
|
2022-07-23 20:32:10 +00:00
|
|
|
|
const _path = process.cwd()
|
2022-09-04 09:33:14 +00:00
|
|
|
|
const getRoot = (root = '') => {
|
2023-03-07 17:52:11 +00:00
|
|
|
|
if (!root) {
|
2022-09-05 02:07:36 +00:00
|
|
|
|
root = `${_path}/`
|
2023-03-07 17:52:11 +00:00
|
|
|
|
} else if (root === 'root' || root === 'yunzai') {
|
|
|
|
|
root = `${_path}/`
|
|
|
|
|
} else if (root === 'miao') {
|
2022-09-04 09:33:14 +00:00
|
|
|
|
root = `${_path}/plugins/miao-plugin/`
|
2023-03-07 17:52:11 +00:00
|
|
|
|
} else {
|
|
|
|
|
root = `${_path}/plugins/${root}/`
|
2022-09-04 09:33:14 +00:00
|
|
|
|
}
|
|
|
|
|
return root
|
|
|
|
|
}
|
2022-06-29 23:05:31 +00:00
|
|
|
|
|
2022-03-26 08:21:44 +00:00
|
|
|
|
let Data = {
|
|
|
|
|
|
2023-03-09 20:34:25 +00:00
|
|
|
|
getRoot,
|
|
|
|
|
|
2022-03-26 08:21:44 +00:00
|
|
|
|
/*
|
|
|
|
|
* 根据指定的path依次检查与创建目录
|
|
|
|
|
* */
|
2022-09-04 09:33:14 +00:00
|
|
|
|
createDir (path = '', root = '', includeFile = false) {
|
|
|
|
|
root = getRoot(root)
|
2022-07-23 20:32:10 +00:00
|
|
|
|
let pathList = path.split('/')
|
2022-09-04 09:33:14 +00:00
|
|
|
|
let nowPath = root
|
2022-03-26 08:21:44 +00:00
|
|
|
|
pathList.forEach((name, idx) => {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
name = name.trim()
|
2022-07-03 21:32:23 +00:00
|
|
|
|
if (!includeFile && idx <= pathList.length - 1) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
nowPath += name + '/'
|
2022-07-03 21:32:23 +00:00
|
|
|
|
if (name) {
|
|
|
|
|
if (!fs.existsSync(nowPath)) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
fs.mkdirSync(nowPath)
|
2022-07-03 21:32:23 +00:00
|
|
|
|
}
|
2022-03-26 08:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 读取json
|
|
|
|
|
* */
|
2022-09-04 09:33:14 +00:00
|
|
|
|
readJSON (file = '', root = '') {
|
|
|
|
|
root = getRoot(root)
|
|
|
|
|
if (fs.existsSync(`${root}/${file}`)) {
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(fs.readFileSync(`${root}/${file}`, 'utf8'))
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(e)
|
|
|
|
|
}
|
2022-04-10 05:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
return {}
|
2022-03-26 08:21:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 写JSON
|
|
|
|
|
* */
|
2023-03-07 17:52:11 +00:00
|
|
|
|
writeJSON (cfg, data, root = '', space = 2) {
|
2023-02-21 17:26:17 +00:00
|
|
|
|
if (arguments.length > 1) {
|
|
|
|
|
return Data.writeJSON({
|
|
|
|
|
name: cfg,
|
|
|
|
|
data,
|
|
|
|
|
space,
|
|
|
|
|
root
|
|
|
|
|
})
|
|
|
|
|
}
|
2022-03-26 08:21:44 +00:00
|
|
|
|
// 检查并创建目录
|
2023-02-21 17:26:17 +00:00
|
|
|
|
let name = cfg.path ? (cfg.path + '/' + cfg.name) : cfg.name
|
|
|
|
|
Data.createDir(name, cfg.root, true)
|
|
|
|
|
root = getRoot(cfg.root)
|
|
|
|
|
data = cfg.data
|
2022-07-23 20:32:10 +00:00
|
|
|
|
delete data._res
|
2023-02-21 17:26:17 +00:00
|
|
|
|
data = JSON.stringify(data, null, cfg.space || 2)
|
|
|
|
|
if (cfg.rn) {
|
|
|
|
|
data = data.replaceAll('\n', '\r\n')
|
|
|
|
|
}
|
|
|
|
|
return fs.writeFileSync(`${root}/${name}`, data)
|
2022-09-04 09:33:14 +00:00
|
|
|
|
},
|
2023-03-07 17:52:11 +00:00
|
|
|
|
|
2023-02-17 20:42:05 +00:00
|
|
|
|
delFile (file, root = '') {
|
|
|
|
|
root = getRoot(root)
|
2022-12-03 19:45:50 +00:00
|
|
|
|
try {
|
2023-02-17 20:42:05 +00:00
|
|
|
|
if (fs.existsSync(`${root}/${file}`)) {
|
|
|
|
|
fs.unlinkSync(`${root}/${file}`)
|
|
|
|
|
}
|
2023-01-17 18:40:17 +00:00
|
|
|
|
return true
|
2022-12-03 19:45:50 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error(`文件删除失败:${error}`)
|
|
|
|
|
}
|
2023-01-17 18:40:17 +00:00
|
|
|
|
return false
|
2022-12-03 19:45:50 +00:00
|
|
|
|
},
|
2023-03-07 17:52:11 +00:00
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
async getCacheJSON (key) {
|
|
|
|
|
try {
|
|
|
|
|
let txt = await redis.get(key)
|
|
|
|
|
if (txt) {
|
|
|
|
|
return JSON.parse(txt)
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(e)
|
|
|
|
|
}
|
|
|
|
|
return {}
|
2022-03-26 08:21:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
async setCacheJSON (key, data, EX = 3600 * 24 * 90) {
|
|
|
|
|
await redis.set(key, JSON.stringify(data), { EX })
|
|
|
|
|
},
|
|
|
|
|
|
2023-01-17 18:40:17 +00:00
|
|
|
|
async redisGet (key, def = {}) {
|
|
|
|
|
try {
|
|
|
|
|
let txt = await redis.get(key)
|
|
|
|
|
if (txt) {
|
|
|
|
|
return JSON.parse(txt)
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(e)
|
|
|
|
|
}
|
|
|
|
|
return def
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async redisSet (key, data, EX = 3600 * 24 * 90) {
|
|
|
|
|
await redis.set(key, JSON.stringify(data), { EX })
|
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
async importModule (file, root = '') {
|
|
|
|
|
root = getRoot(root)
|
2022-06-29 23:05:31 +00:00
|
|
|
|
if (!/\.js$/.test(file)) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
file = file + '.js'
|
2022-06-29 23:05:31 +00:00
|
|
|
|
}
|
2022-09-04 09:33:14 +00:00
|
|
|
|
if (fs.existsSync(`${root}/${file}`)) {
|
|
|
|
|
try {
|
2022-09-25 13:56:10 +00:00
|
|
|
|
let data = await import(`file://${root}/${file}?t=${new Date() * 1}`)
|
2022-09-04 09:33:14 +00:00
|
|
|
|
return data || {}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(e)
|
|
|
|
|
}
|
2022-06-29 23:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
return {}
|
|
|
|
|
},
|
|
|
|
|
|
2022-09-23 22:57:42 +00:00
|
|
|
|
async importDefault (file, root) {
|
|
|
|
|
let ret = await Data.importModule(file, root)
|
|
|
|
|
return ret.default || {}
|
|
|
|
|
},
|
|
|
|
|
|
2022-08-18 10:13:42 +00:00
|
|
|
|
async importCfg (key) {
|
2023-03-07 17:52:11 +00:00
|
|
|
|
let sysCfg = await Data.importModule(`config/system/${key}_system.js`, 'miao')
|
|
|
|
|
let diyCfg = await Data.importModule(`config/${key}.js`, 'miao')
|
2022-08-18 10:13:42 +00:00
|
|
|
|
if (diyCfg.isSys) {
|
|
|
|
|
console.error(`miao-plugin: config/${key}.js无效,已忽略`)
|
|
|
|
|
console.error(`如需配置请复制config/${key}_default.js为config/${key}.js,请勿复制config/system下的系统文件`)
|
|
|
|
|
diyCfg = {}
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
sysCfg,
|
|
|
|
|
diyCfg
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2022-03-26 08:21:44 +00:00
|
|
|
|
/*
|
|
|
|
|
* 返回一个从 target 中选中的属性的对象
|
|
|
|
|
*
|
|
|
|
|
* keyList : 获取字段列表,逗号分割字符串
|
|
|
|
|
* key1, key2, toKey1:fromKey1, toKey2:fromObj.key
|
|
|
|
|
*
|
|
|
|
|
* defaultData: 当某个字段为空时会选取defaultData的对应内容
|
|
|
|
|
* toKeyPrefix:返回数据的字段前缀,默认为空。defaultData中的键值无需包含toKeyPrefix
|
|
|
|
|
*
|
|
|
|
|
* */
|
|
|
|
|
|
2022-07-23 20:32:10 +00:00
|
|
|
|
getData (target, keyList = '', cfg = {}) {
|
|
|
|
|
target = target || {}
|
|
|
|
|
let defaultData = cfg.defaultData || {}
|
|
|
|
|
let ret = {}
|
2022-03-26 08:21:44 +00:00
|
|
|
|
// 分割逗号
|
2022-07-23 20:32:10 +00:00
|
|
|
|
if (typeof (keyList) === 'string') {
|
|
|
|
|
keyList = keyList.split(',')
|
2022-03-26 08:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lodash.forEach(keyList, (keyCfg) => {
|
|
|
|
|
// 处理通过:指定 toKey & fromKey
|
2022-07-23 20:32:10 +00:00
|
|
|
|
let _keyCfg = keyCfg.split(':')
|
|
|
|
|
let keyTo = _keyCfg[0].trim()
|
|
|
|
|
let keyFrom = (_keyCfg[1] || _keyCfg[0]).trim()
|
|
|
|
|
let keyRet = keyTo
|
2022-03-26 08:21:44 +00:00
|
|
|
|
if (cfg.lowerFirstKey) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
keyRet = lodash.lowerFirst(keyRet)
|
2022-03-26 08:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
if (cfg.keyPrefix) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
keyRet = cfg.keyPrefix + keyRet
|
2022-03-26 08:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
// 通过Data.getVal获取数据
|
2022-07-23 20:32:10 +00:00
|
|
|
|
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg)
|
2022-03-26 08:21:44 +00:00
|
|
|
|
})
|
2022-07-23 20:32:10 +00:00
|
|
|
|
return ret
|
2022-03-26 08:21:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-07-23 20:32:10 +00:00
|
|
|
|
getVal (target, keyFrom, defaultValue) {
|
|
|
|
|
return lodash.get(target, keyFrom, defaultValue)
|
2022-04-03 22:06:03 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
// 异步池,聚合请求
|
2022-07-23 20:32:10 +00:00
|
|
|
|
async asyncPool (poolLimit, array, iteratorFn) {
|
|
|
|
|
const ret = [] // 存储所有的异步任务
|
|
|
|
|
const executing = [] // 存储正在执行的异步任务
|
2022-04-03 22:47:06 +00:00
|
|
|
|
for (const item of array) {
|
|
|
|
|
// 调用iteratorFn函数创建异步任务
|
2022-07-23 20:32:10 +00:00
|
|
|
|
const p = Promise.resolve().then(() => iteratorFn(item, array))
|
2022-04-03 22:47:06 +00:00
|
|
|
|
// 保存新的异步任务
|
2022-07-23 20:32:10 +00:00
|
|
|
|
ret.push(p)
|
2022-04-03 22:47:06 +00:00
|
|
|
|
|
|
|
|
|
// 当poolLimit值小于或等于总任务个数时,进行并发控制
|
|
|
|
|
if (poolLimit <= array.length) {
|
|
|
|
|
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
|
2022-07-23 20:32:10 +00:00
|
|
|
|
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
|
|
|
|
|
executing.push(e) // 保存正在执行的异步任务
|
2022-04-03 22:47:06 +00:00
|
|
|
|
if (executing.length >= poolLimit) {
|
|
|
|
|
// 等待较快的任务执行完成
|
2022-07-23 20:32:10 +00:00
|
|
|
|
await Promise.race(executing)
|
2022-04-03 22:47:06 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-23 20:32:10 +00:00
|
|
|
|
return Promise.all(ret)
|
2022-04-03 22:47:06 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
// sleep
|
2022-07-23 20:32:10 +00:00
|
|
|
|
sleep (ms) {
|
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms))
|
2022-06-30 18:53:05 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
// 获取默认值
|
2022-07-23 20:32:10 +00:00
|
|
|
|
def () {
|
2022-06-30 18:53:05 +00:00
|
|
|
|
for (let idx in arguments) {
|
|
|
|
|
if (!lodash.isUndefined(arguments[idx])) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
return arguments[idx]
|
2022-06-30 18:53:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
2023-05-09 03:00:37 +00:00
|
|
|
|
async forEach (data, fn) {
|
|
|
|
|
if (lodash.isArray(data)) {
|
|
|
|
|
for (let idx = 0; idx < data.length; idx++) {
|
|
|
|
|
let ret = fn(data[idx], idx)
|
|
|
|
|
if (ret instanceof Promise) {
|
|
|
|
|
ret = await ret
|
|
|
|
|
}
|
|
|
|
|
if (ret === false) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (lodash.isPlainObject(data)) {
|
|
|
|
|
for (const idx in data) {
|
|
|
|
|
let ret = fn(data[idx], idx)
|
|
|
|
|
if (ret instanceof Promise) {
|
|
|
|
|
ret = await ret
|
|
|
|
|
}
|
|
|
|
|
if (ret === false) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2022-09-04 09:33:14 +00:00
|
|
|
|
// 循环字符串回调
|
2022-06-30 18:53:05 +00:00
|
|
|
|
eachStr: (arr, fn) => {
|
|
|
|
|
if (lodash.isString(arr)) {
|
2022-07-23 20:32:10 +00:00
|
|
|
|
arr = arr.replace(/\s*(;|;|、|,)\s*/, ',')
|
|
|
|
|
arr = arr.split(',')
|
2022-09-23 21:59:30 +00:00
|
|
|
|
} else if (lodash.isNumber(arr)) {
|
|
|
|
|
arr = [arr.toString()]
|
2022-06-30 18:53:05 +00:00
|
|
|
|
}
|
|
|
|
|
lodash.forEach(arr, (str, idx) => {
|
|
|
|
|
if (!lodash.isUndefined(str)) {
|
|
|
|
|
fn(str.trim ? str.trim() : str, idx)
|
|
|
|
|
}
|
2022-07-23 20:32:10 +00:00
|
|
|
|
})
|
2022-09-04 21:03:23 +00:00
|
|
|
|
},
|
2022-04-03 22:06:03 +00:00
|
|
|
|
|
2022-09-04 21:03:23 +00:00
|
|
|
|
regRet (reg, txt, idx) {
|
|
|
|
|
if (reg && txt) {
|
|
|
|
|
let ret = reg.exec(txt)
|
|
|
|
|
if (ret && ret[idx]) {
|
|
|
|
|
return ret[idx]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2022-04-03 22:47:06 +00:00
|
|
|
|
}
|
2022-04-03 22:06:03 +00:00
|
|
|
|
|
2022-07-23 20:32:10 +00:00
|
|
|
|
export default Data
|