删除 xlsx
This commit is contained in:
parent
76c63405bb
commit
db55e7702e
11
package.json
11
package.json
|
@ -21,7 +21,7 @@
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"https-proxy-agent": "7.0.2",
|
"https-proxy-agent": "7.0.2",
|
||||||
"icqq": "^0.6.3",
|
"icqq": "^0.6.5",
|
||||||
"image-size": "^1.0.2",
|
"image-size": "^1.0.2",
|
||||||
"inquirer": "^9.2.12",
|
"inquirer": "^9.2.12",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -30,17 +30,16 @@
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"node-schedule": "^2.1.1",
|
"node-schedule": "^2.1.1",
|
||||||
"node-xlsx": "^0.23.0",
|
|
||||||
"oicq": "^2.3.1",
|
"oicq": "^2.3.1",
|
||||||
"pm2": "^5.3.0",
|
"pm2": "^5.3.0",
|
||||||
"puppeteer": "^21.5.1",
|
"puppeteer": "^21.6.0",
|
||||||
"redis": "^4.6.10",
|
"redis": "^4.6.11",
|
||||||
"sequelize": "^6.34.0",
|
"sequelize": "^6.35.1",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
"yaml": "^2.3.4"
|
"yaml": "^2.3.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.53.0",
|
"eslint": "^8.55.0",
|
||||||
"eslint-config-standard": "^17.1.0",
|
"eslint-config-standard": "^17.1.0",
|
||||||
"eslint-plugin-import": "^2.29.0",
|
"eslint-plugin-import": "^2.29.0",
|
||||||
"eslint-plugin-n": "^16.3.1",
|
"eslint-plugin-n": "^16.3.1",
|
||||||
|
|
|
@ -52,9 +52,7 @@
|
||||||
|#武器统计|统计抽卡数据,按卡池统计|
|
|#武器统计|统计抽卡数据,按卡池统计|
|
||||||
|#常驻统计|统计抽卡数据,按卡池统计|
|
|#常驻统计|统计抽卡数据,按卡池统计|
|
||||||
|#记录帮助|抽卡记录导入说明|
|
|#记录帮助|抽卡记录导入说明|
|
||||||
|#导出记录|抽卡记录xlsx导出|
|
|#导出记录|抽卡记录json导出|
|
||||||
|#导出记录json|抽卡记录json导出|
|
|
||||||
|xlsx文件导入|xlsx导入,统一可交换祈愿记录v2.2|
|
|
||||||
|json文件导入|json导入,统一可交换祈愿记录v2.2|
|
|json文件导入|json导入,统一可交换祈愿记录v2.2|
|
||||||
|
|
||||||
| 其他指令 | 说明|
|
| 其他指令 | 说明|
|
||||||
|
|
|
@ -22,10 +22,6 @@ export class gcLog extends plugin {
|
||||||
reg: '^#txt日志文件导入记录$',
|
reg: '^#txt日志文件导入记录$',
|
||||||
fnc: 'logFile'
|
fnc: 'logFile'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
reg: '^#xlsx文件导入记录$',
|
|
||||||
fnc: 'logXlsx'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
reg: '^#json文件导入记录$',
|
reg: '^#json文件导入记录$',
|
||||||
fnc: 'logJson'
|
fnc: 'logJson'
|
||||||
|
@ -35,7 +31,7 @@ export class gcLog extends plugin {
|
||||||
fnc: 'getLog'
|
fnc: 'getLog'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
reg: '^#*(原神|星铁)?导出记录(excel|xlsx|json)*$',
|
reg: '^#*(原神|星铁)?导出记录(json)?$',
|
||||||
fnc: 'exportLog'
|
fnc: 'exportLog'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -72,10 +68,6 @@ export class gcLog extends plugin {
|
||||||
this.e.msg = '#txt日志文件导入记录'
|
this.e.msg = '#txt日志文件导入记录'
|
||||||
if (name.includes('output')) return true
|
if (name.includes('output')) return true
|
||||||
}
|
}
|
||||||
if (/(.*)[1-9][0-9]{8}(.*).xlsx$/ig.test(name)) {
|
|
||||||
this.e.msg = '#xlsx文件导入记录'
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (/(.*)[1-9][0-9]{8}(.*).json/ig.test(name)) {
|
if (/(.*)[1-9][0-9]{8}(.*).json/ig.test(name)) {
|
||||||
this.e.msg = '#json文件导入记录'
|
this.e.msg = '#json文件导入记录'
|
||||||
return true
|
return true
|
||||||
|
@ -142,27 +134,7 @@ export class gcLog extends plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
let exportLog = new ExportLog(this.e)
|
let exportLog = new ExportLog(this.e)
|
||||||
|
return await exportLog.exportJson()
|
||||||
if (this.e.msg.includes('json')) {
|
|
||||||
return await exportLog.exportJson()
|
|
||||||
} else {
|
|
||||||
await this.e.reply('如需要将此记录导入到其他平台,请导出json格式文件')
|
|
||||||
return await exportLog.exportXlsx()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async logXlsx () {
|
|
||||||
if (!this.e.isPrivate) {
|
|
||||||
await this.e.reply('请私聊发送日志文件', false, { at: true })
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.e.file) {
|
|
||||||
await this.e.reply('请发送xlsx文件')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
await this.e.reply('如果是星铁记录,请在【原始数据】工作表复制【gacha_type】列,粘贴并把此标题重命名为【srgf_gacha_type】,否则可能无法正确识别')
|
|
||||||
await new ExportLog(this.e).logXlsx()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async logJson () {
|
async logJson () {
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
desc: 按卡池统计抽卡数据
|
desc: 按卡池统计抽卡数据
|
||||||
- icon: excel
|
- icon: excel
|
||||||
title: 导出记录、导入记录
|
title: 导出记录、导入记录
|
||||||
desc: 导出导入xlsx、json抽卡记录
|
desc: 导出导入json抽卡记录
|
||||||
- icon: 纠缠之缘
|
- icon: 纠缠之缘
|
||||||
title: 十连 十连2 定轨 十连武器
|
title: 十连 十连2 定轨 十连武器
|
||||||
desc: 真实模拟抽卡
|
desc: 真实模拟抽卡
|
||||||
|
|
|
@ -6,8 +6,6 @@ import moment from 'moment'
|
||||||
import GachaLog from './gachaLog.js'
|
import GachaLog from './gachaLog.js'
|
||||||
import lodash from 'lodash'
|
import lodash from 'lodash'
|
||||||
|
|
||||||
let xlsx = {}
|
|
||||||
|
|
||||||
export default class ExportLog extends base {
|
export default class ExportLog extends base {
|
||||||
constructor(e) {
|
constructor(e) {
|
||||||
super(e)
|
super(e)
|
||||||
|
@ -56,12 +54,6 @@ export default class ExportLog extends base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async initXlsx() {
|
|
||||||
if (!lodash.isEmpty(xlsx)) return xlsx
|
|
||||||
|
|
||||||
xlsx = await import('node-xlsx')
|
|
||||||
}
|
|
||||||
|
|
||||||
async exportJson() {
|
async exportJson() {
|
||||||
if (!this.e.isSr) {
|
if (!this.e.isSr) {
|
||||||
await common.downFile('https://api.uigf.org/dict/genshin/chs.json', './temp/uigf/genshin.json')
|
await common.downFile('https://api.uigf.org/dict/genshin/chs.json', './temp/uigf/genshin.json')
|
||||||
|
@ -107,44 +99,6 @@ export default class ExportLog extends base {
|
||||||
fs.unlink(saveFile, () => { })
|
fs.unlink(saveFile, () => { })
|
||||||
}
|
}
|
||||||
|
|
||||||
async exportXlsx() {
|
|
||||||
await this.getUid()
|
|
||||||
|
|
||||||
if (!this.uid) return false
|
|
||||||
|
|
||||||
await this.initXlsx()
|
|
||||||
|
|
||||||
logger.mark(`${this.e.logFnc} 开始导出${this.uid}.xlsx`)
|
|
||||||
|
|
||||||
let res = this.getAllList()
|
|
||||||
|
|
||||||
/** 处理卡池数据 */
|
|
||||||
let xlsxData = this.xlsxDataPool(res)
|
|
||||||
/** 处理所有数据 */
|
|
||||||
xlsxData.push(this.xlsxDataAll(res))
|
|
||||||
|
|
||||||
/** node-xlsx导出的buffer有点大.. */
|
|
||||||
let buffer = xlsx.build(xlsxData)
|
|
||||||
let saveFile = `${this.path}${this.uid}/${this.uid}.xlsx`
|
|
||||||
|
|
||||||
fs.writeFileSync(saveFile, Buffer.from(buffer))
|
|
||||||
|
|
||||||
logger.mark(`${this.e.logFnc} 导出成功${this.uid}.xlsx`)
|
|
||||||
|
|
||||||
this.e.reply(`记录文件${this.uid}.xlsx上传中,请耐心等待...`)
|
|
||||||
|
|
||||||
res = await this.e.friend.sendFile(saveFile).catch((err) => {
|
|
||||||
this.e.reply(`发送文件${this.uid}.xlsx失败,请稍后再试`)
|
|
||||||
logger.error(`${this.e.logFnc} 发送文件失败 ${JSON.stringify(err)}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
let line = xlsxData[xlsxData.length - 1].data.length - 1
|
|
||||||
if (res) this.e.reply(`${this.uid}.xlsx上传成功,共${line}条\n请接收文件`)
|
|
||||||
|
|
||||||
/** 删除文件 */
|
|
||||||
fs.unlink(saveFile, () => { })
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUid() {
|
async getUid() {
|
||||||
let gachLog = new GachaLog(this.e)
|
let gachLog = new GachaLog(this.e)
|
||||||
let uid = await gachLog.getUid()
|
let uid = await gachLog.getUid()
|
||||||
|
@ -215,178 +169,6 @@ export default class ExportLog extends base {
|
||||||
return JSON.parse(fs.readFileSync(json, 'utf8'))
|
return JSON.parse(fs.readFileSync(json, 'utf8'))
|
||||||
}
|
}
|
||||||
|
|
||||||
xlsxDataPool(data) {
|
|
||||||
let xlsxData = []
|
|
||||||
|
|
||||||
for (let v of this.pool(this.game)) {
|
|
||||||
let poolData = [
|
|
||||||
[
|
|
||||||
'时间', '名称', '物品类型', '星级', '祈愿类型'
|
|
||||||
]
|
|
||||||
]
|
|
||||||
for (let log of data[v.type]) {
|
|
||||||
poolData.push([
|
|
||||||
log.time, log.name, log.item_type, log.rank_type, log.gacha_type
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
let sheetOptions = {
|
|
||||||
'!cols': [{ wch: 20 }, { wch: 20 }, { wch: 10 }, { wch: 10 }, { wch: 10 }]
|
|
||||||
}
|
|
||||||
xlsxData.push({ name: `${v.typeName}祈愿`, data: poolData, options: sheetOptions })
|
|
||||||
}
|
|
||||||
|
|
||||||
return xlsxData
|
|
||||||
}
|
|
||||||
|
|
||||||
xlsxDataAll(data) {
|
|
||||||
let ui = this.e.isSr ? 'sr' : 'ui'
|
|
||||||
let list = [
|
|
||||||
[
|
|
||||||
'count', 'gacha_type', 'id', 'item_id', 'item_type', 'lang', 'name', 'rank_type', 'time', 'uid', `${ui}gf_gacha_type`
|
|
||||||
]
|
|
||||||
]
|
|
||||||
for (let v of data.list) {
|
|
||||||
let tmp = []
|
|
||||||
if (this.e.isSr) v.srgf_gacha_type = v.gacha_type
|
|
||||||
for (let i of list[0]) {
|
|
||||||
if (i == 'id' || i == `${ui}gf_gacha_type`) v[i] = String(v[i])
|
|
||||||
tmp.push(v[i])
|
|
||||||
}
|
|
||||||
list.push(tmp)
|
|
||||||
}
|
|
||||||
let sheetOptions = {
|
|
||||||
'!cols': [{ wch: 10 }, { wch: 10 }, { wch: 20 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 20 }, { wch: 10 }, { wch: 20 }, { wch: 10 }, { wch: 10 }]
|
|
||||||
}
|
|
||||||
|
|
||||||
return { name: '原始数据', data: list, options: sheetOptions }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** xlsx导入抽卡记录 */
|
|
||||||
async logXlsx() {
|
|
||||||
await this.initXlsx()
|
|
||||||
|
|
||||||
let uid = /[1-9][0-9]{8}/g.exec(this.e.file.name)[0]
|
|
||||||
let textPath = `${this.path}${this.e.file.name}`
|
|
||||||
/** 获取文件下载链接 */
|
|
||||||
let fileUrl = await this.e.friend.getFileUrl(this.e.file.fid)
|
|
||||||
|
|
||||||
let ret = await common.downFile(fileUrl, textPath)
|
|
||||||
if (!ret) {
|
|
||||||
this.e.reply('下载xlsx文件错误')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let list = xlsx.parse(textPath)
|
|
||||||
list = lodash.keyBy(list, 'name')
|
|
||||||
|
|
||||||
// 适配StarRailExport导出的xlsx,该xlsx没有原始数据表.
|
|
||||||
let rawData = list['原始数据'] ? list['原始数据'] : list['rawData'];
|
|
||||||
if (!list['原始数据'] && list['rawData']) {
|
|
||||||
// 获取rawData的time字段(第9列)的索引
|
|
||||||
const timeIndex = 8;
|
|
||||||
|
|
||||||
// 对rawData进行排序(按照time字段,除第一行外)
|
|
||||||
const headerRow = rawData.data[0]; // 保存标题行
|
|
||||||
const dataToSort = rawData.data.slice(1); // 除第一行外的数据
|
|
||||||
|
|
||||||
dataToSort.sort((a, b) => {
|
|
||||||
return moment(a[timeIndex]).format('x') - moment(b[timeIndex]).format('x');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重新构建rawData的数据,包括标题行
|
|
||||||
rawData.data = [headerRow, ...dataToSort];
|
|
||||||
|
|
||||||
// 将数据写回原文件,重新读取
|
|
||||||
fs.writeFileSync(textPath, xlsx.build([rawData]));
|
|
||||||
list = lodash.keyBy(xlsx.parse(textPath), 'name');
|
|
||||||
rawData = list['rawData'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rawData) {
|
|
||||||
this.e.reply('xlsx文件内容错误:非统一祈愿记录标准')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rawData.data[0].includes('srgf_gacha_type')) {
|
|
||||||
this.e.isSr = true
|
|
||||||
this.game = 'sr'
|
|
||||||
}
|
|
||||||
/** 处理xlsx数据 */
|
|
||||||
let data = this.dealXlsx(rawData.data);
|
|
||||||
if (!data) return false
|
|
||||||
|
|
||||||
/** 保存json */
|
|
||||||
let msg = []
|
|
||||||
for (let type in data) {
|
|
||||||
let typeName = this.typeName(this.game)
|
|
||||||
if (!typeName[type]) continue
|
|
||||||
let gachLog = new GachaLog(this.e)
|
|
||||||
gachLog.uid = uid
|
|
||||||
gachLog.type = type
|
|
||||||
gachLog.writeJson(data[type])
|
|
||||||
|
|
||||||
msg.push(`${typeName[type]}记录:${data[type].length}条`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除文件 */
|
|
||||||
fs.unlink(textPath, () => { })
|
|
||||||
|
|
||||||
await this.e.reply(`${this.e.file.name},${this.e.isSr ? '星铁' : '原神'}记录导入成功\n${msg.join('\n')}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
dealXlsx(list) {
|
|
||||||
let ui = this.e.isSr ? 'sr' : 'ui'
|
|
||||||
/** 必要字段 */
|
|
||||||
let reqField = ['gacha_type', 'item_type', 'name', 'time', `${ui}gf_gacha_type`]
|
|
||||||
/** 不是必要字段 */
|
|
||||||
let noReqField = ['id', 'uid', 'count', 'item_id', 'lang', 'rank_type']
|
|
||||||
|
|
||||||
let field = {}
|
|
||||||
for (let i in list[0]) {
|
|
||||||
field[list[0][i]] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 判断字段 */
|
|
||||||
for (let v of reqField) {
|
|
||||||
if (!field[v]) {
|
|
||||||
let tips = v === 'srgf_gacha_type' ? '\n请在【原始数据】工作表复制【gacha_type】列,粘贴并把此标题重命名为【srgf_gacha_type】' : ''
|
|
||||||
this.e.reply(`xlsx文件内容错误:缺少必要字段${v}${tips}`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 倒序 */
|
|
||||||
if (moment(list[1][field.time]).format('x') < moment(list[list.length - 1][field.time]).format('x')) {
|
|
||||||
list = list.reverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = {}
|
|
||||||
for (let v of list) {
|
|
||||||
if (v[field.name] == 'name') continue
|
|
||||||
if (!data[v[field[`${ui}gf_gacha_type`]]]) data[v[field[`${ui}gf_gacha_type`]]] = []
|
|
||||||
|
|
||||||
let tmp = {}
|
|
||||||
/** 加入必要字段 */
|
|
||||||
for (let re of reqField) {
|
|
||||||
tmp[re] = v[field[re]]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 加入非必要字段 */
|
|
||||||
for (let noRe of noReqField) {
|
|
||||||
if (field[noRe]) {
|
|
||||||
tmp[noRe] = v[field[noRe]]
|
|
||||||
} else {
|
|
||||||
tmp[noRe] = ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data[v[field[`${ui}gf_gacha_type`]]].push(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
/** json导入抽卡记录 */
|
/** json导入抽卡记录 */
|
||||||
async logJson() {
|
async logJson() {
|
||||||
let uid = /[1-9][0-9]{8}/g.exec(this.e.file.name)[0]
|
let uid = /[1-9][0-9]{8}/g.exec(this.e.file.name)[0]
|
||||||
|
|
Loading…
Reference in New Issue