Miao-Yunzai/plugins/genshin/model/exportLog.js

386 lines
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import base from './base.js'
import cfg from '../../../lib/config/config.js'
import common from '../../../lib/common/common.js'
import fs from 'node:fs'
import moment from 'moment'
import GachaLog from './gachaLog.js'
import lodash from 'lodash'
let xlsx = {}
export default class ExportLog extends base {
constructor (e) {
super(e)
this.model = 'gachaLog'
this.urlKey = `${this.prefix}url:`
/** 绑定的uid */
this.uidKey = `Yz:genshin:mys:qq-uid:${this.userId}`
this.path = `./data/gachaJson/${this.e.user_id}/`
this.pool = [
{ type: 301, typeName: '角色活动' },
{ type: 302, typeName: '武器活动' },
{ type: 200, typeName: '常驻' }
]
this.typeName = {
301: '角色',
302: '武器',
200: '常驻'
}
}
async initXlsx () {
if (!lodash.isEmpty(xlsx)) return xlsx
xlsx = await import('node-xlsx')
}
async exportJson () {
await this.getUid()
if (!this.uid) return false
let list = this.getAllList().list
let data = {
info: {
uid: this.uid,
lang: list[0].lang,
export_time: moment().format('YYYY-MM-DD HH:mm:ss'),
export_timestamp: moment().format('X'),
export_app: 'Yunzai-Bot',
export_app_version: cfg.package.version,
uigf_version: 'v2.2'
},
list
}
let saveFile = `${this.path}${this.uid}/${this.uid}.json`
fs.writeFileSync(saveFile, JSON.stringify(data, '', '\t'))
logger.mark(`${this.e.logFnc} 导出成功${this.uid}.json`)
this.e.reply(`导出成功:${this.uid}.json${list.length}\n请接收文件`)
await this.e.friend.sendFile(saveFile).catch((err) => {
logger.error(`${this.e.logFnc} 发送文件失败 ${JSON.stringify(err)}`)
})
/** 删除文件 */
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 () {
let gachLog = new GachaLog(this.e)
let uid = await gachLog.getUid()
if (!uid) return false
this.uid = uid
return this.uid
}
getAllList () {
let res = {
list: []
}
let tmpId = {}
for (let v of this.pool) {
let json = `${this.path}${this.uid}/${v.type}.json`
if (fs.existsSync(json)) {
json = JSON.parse(fs.readFileSync(json, 'utf8'))
json = json.reverse()
} else {
json = []
}
res[v.type] = json
for (let v of json) {
if (v.gacha_type == 301 || v.gacha_type == 400) {
v.uigf_gacha_type = '301'
} else {
v.uigf_gacha_type = v.gacha_type
}
let id = v.id
if (!id) {
id = moment(v.time).format('x') + '000000'
v.id = id
} else {
if (id.length == 13) {
v.id = `${id}000000`
}
}
if (tmpId[id]) {
let newId = `${id}00000${tmpId[id].length}`
tmpId[id].push(newId)
v.id = newId
} else {
tmpId[id] = [id]
}
res.list.push(v)
}
}
res.list = lodash.orderBy(res.list, ['id', 'asc'])
return res
}
loadJson (json) {
if (!fs.existsSync(json)) return []
return JSON.parse(fs.readFileSync(json, 'utf8'))
}
xlsxDataPool (data) {
let xlsxData = []
for (let v of this.pool) {
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 list = [
[
'count', 'gacha_type', 'id', 'item_id', 'item_type', 'lang', 'name', 'rank_type', 'time', 'uid', 'uigf_gacha_type'
]
]
for (let v of data.list) {
let tmp = []
for (let i of list[0]) {
if (i == 'id' || i == 'uigf_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')
if (!list['原始数据']) {
this.e.reply('xlsx文件内容错误非统一祈愿记录标准')
return false
}
/** 处理xlsx数据 */
let data = this.dealXlsx(list['原始数据'].data)
if (!data) return false
/** 保存json */
let msg = []
for (let type in data) {
if (!this.typeName[type]) continue
let gachLog = new GachaLog(this.e)
gachLog.uid = uid
gachLog.type = type
gachLog.writeJson(data[type])
msg.push(`${this.typeName[type]}记录:${data[type].length}`)
}
/** 删除文件 */
fs.unlink(textPath, () => {})
await this.e.reply(`${this.e.file.name},导入成功\n${msg.join('\n')}`)
}
dealXlsx (list) {
/** 必要字段 */
let reqField = ['uigf_gacha_type', 'gacha_type', 'item_type', 'name', 'time']
/** 不是必要字段 */
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]) {
this.e.reply(`xlsx文件内容错误缺少必要字段${v}`)
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.uigf_gacha_type]]) data[v[field.uigf_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.uigf_gacha_type]].push(tmp)
}
return data
}
/** json导入抽卡记录 */
async logJson () {
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('下载json文件错误')
return false
}
let json = {}
try {
json = JSON.parse(fs.readFileSync(textPath, 'utf8'))
} catch (error) {
this.e.reply(`${this.e.file.name},json格式错误`)
return false
}
if (lodash.isEmpty(json) || !json.list) {
this.e.reply('json文件内容错误非统一祈愿记录标准')
return false
}
let data = this.dealJson(json.list)
if (!data) return false
/** 保存json */
let msg = []
for (let type in data) {
if (!this.typeName[type]) continue
let gachLog = new GachaLog(this.e)
gachLog.uid = uid
gachLog.type = type
gachLog.writeJson(data[type])
msg.push(`${this.typeName[type]}记录:${data[type].length}`)
}
/** 删除文件 */
fs.unlink(textPath, () => {})
await this.e.reply(`${this.e.file.name},导入成功\n${msg.join('\n')}`)
}
dealJson (list) {
let data = {}
/** 必要字段 */
let reqField = ['gacha_type', 'item_type', 'name', 'time']
for (let v of reqField) {
if (!list[0][v]) {
this.e.reply(`json文件内容错误缺少必要字段${v}`)
return false
}
}
/** 倒序 */
if (moment(list[0].time).format('x') < moment(list[list.length - 1].time).format('x')) {
list = list.reverse()
}
for (let v of list) {
if (!data[v.uigf_gacha_type]) data[v.uigf_gacha_type] = []
data[v.uigf_gacha_type].push(v)
}
return data
}
}