适配星铁抽卡记录导入导出,修正“留影叙佳期”正则 (#274)

* 修正留影叙佳期正则,降低触发频率

* 适配星铁抽卡记录导出

* 适配Github - biuuu原神/星铁抽卡导出工具的抽卡记录导入

---------

Co-authored-by: James <qgj087388718@163.com>
Co-authored-by: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com>
This commit is contained in:
8852690 2023-10-13 02:52:05 +08:00 committed by GitHub
parent 18e8a8efa1
commit 60a82526cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 67 deletions

View File

@ -8,7 +8,7 @@ import LogCount from '../model/logCount.js'
const _path = process.cwd() + '/plugins/genshin'
export class gcLog extends plugin {
constructor () {
constructor() {
super({
name: '抽卡记录',
dsc: '抽卡记录数据统计',
@ -20,15 +20,15 @@ export class gcLog extends plugin {
fnc: 'logUrl'
},
{
reg: '^#txt日志文件导入记录$',
reg: '#txt(日志)?(文件)?导入记录',
fnc: 'logFile'
},
{
reg: '^#xlsx文件导入记录$',
reg: '#*(原神|星铁)?(xlsx|excel)(文件)?导入记录',
fnc: 'logXlsx'
},
{
reg: '^#json文件导入记录$',
reg: '#*(原神|星铁)?json(文件)?导入记录',
fnc: 'logJson'
},
{
@ -36,7 +36,7 @@ export class gcLog extends plugin {
fnc: 'getLog'
},
{
reg: '^#*导出记录(excel|xlsx|json)*$',
reg: '^#*(原神|星铁)?导出记录(excel|xlsx|json)*$',
fnc: 'exportLog'
},
{
@ -57,7 +57,7 @@ export class gcLog extends plugin {
this.androidUrl = 'https://docs.qq.com/doc/DUWpYaXlvSklmVXlX'
}
async init () {
async init() {
let file = ['./data/gachaJson', './data/srJson', './temp/html/StarRail']
for (let i of file) {
if (!fs.existsSync(i)) {
@ -66,7 +66,7 @@ export class gcLog extends plugin {
}
}
accept () {
accept() {
if (this.e.file && this.e.isPrivate) {
let name = this.e.file?.name
if (name.includes('txt')) {
@ -89,7 +89,7 @@ export class gcLog extends plugin {
}
/** 抽卡记录链接 */
async logUrl () {
async logUrl() {
if (!this.e.isPrivate) {
this.e.reply('请私聊发送链接', false, { at: true })
return true
@ -103,7 +103,7 @@ export class gcLog extends plugin {
}
/** 发送output_log.txt日志文件 */
async logFile () {
async logFile() {
if (!this.e.isPrivate) {
await this.e.reply('请私聊发送日志文件', false, { at: true })
return true
@ -126,7 +126,7 @@ export class gcLog extends plugin {
}
/** #抽卡记录 */
async getLog () {
async getLog() {
this.e.isAll = !!(this.e.msg.includes('全部'))
let data = await new GachaLog(this.e).getLogData()
if (!data) return
@ -139,7 +139,7 @@ export class gcLog extends plugin {
}
/** 导出记录 */
async exportLog () {
async exportLog() {
if (this.e.isGroup) {
await this.reply('请私聊导出', false, { at: true })
return
@ -154,39 +154,59 @@ export class gcLog extends plugin {
}
}
async logXlsx () {
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
}
const gsTips = `不支持https://github.com/biuuu/genshin-wish-export项目导出的excel文件,如果是该项目的文件请发送任意消息取消excel导入后使用【#json导入记录】`;
const srTips = `注:适配https://github.com/biuuu/star-rail-warp-export项目导出的excel文件`;
await new ExportLog(this.e).logXlsx()
await this.e.reply(`请发送xlsx文件该文件需要以${this.e?.isSr ? '*' : '#'}的uid命名100000000.xlsx\n否则可能无法正确识别,如果误触可发送任意消息取消导入\n${this.e?.isSr ? srTips : gsTips}`);
this.setContext('importLogXlsx');
}
async logJson () {
async importLogXlsx() {
if (!this.e.file) {
await this.e.reply(`未检测到excel文件操作已取消请重新发送【${this.e?.isSr ? '*' : '#'}excel导入记录】`);
}
else {
this.e.isSr = this.getContext()?.importLogXlsx.isSr;
await new ExportLog(this.e).logXlsx();
}
this.finish('importLogXlsx');
}
async logJson() {
if (!this.e.isPrivate) {
await this.e.reply('请私聊发送Json文件', false, { at: true })
await this.e.reply('请私聊发送日志文件', false, { at: true })
return true
}
if (!this.e.file) {
await this.e.reply('请发送Json文件')
return true
}
const gsTips = `适配https://github.com/biuuu/genshin-wish-export项目导出的json文件`;
const srTips = `注:适配https://github.com/biuuu/star-rail-warp-export项目导出的json文件`;
await new ExportLog(this.e).logJson()
await this.e.reply(`请发送json文件该文件需要以${this.e?.isSr ? '*' : '#'}的uid命名\n100000000.json否则可能无法正确识别如果误触可发送任意消息取消导入\n${this.e?.isSr ? srTips : gsTips}`);
this.setContext('importLogJson');
}
async help () {
async importLogJson() {
this.e.isSr = this.getContext()?.importLogJson.isSr;
if (!this.e.file) {
await this.e.reply(`未检测到json文件操作已取消请重新发送【${this.e?.isSr ? '*' : '#'}json导入记录】`);
}
else {
await new ExportLog(this.e).logJson();
}
this.finish('importLogJson');
}
async help() {
await this.e.reply(segment.image(`file://${_path}/resources/logHelp/记录帮助.png`))
}
async helpPort () {
async helpPort() {
let msg = this.e.msg.replace(/#|帮助/g, '')
if (['电脑', 'pc'].includes(msg)) {
@ -198,7 +218,7 @@ export class gcLog extends plugin {
}
}
async logCount () {
async logCount() {
let data = await new LogCount(this.e).count()
if (!data) return
let img = await puppeteer.screenshot(`${data.srtempFile}logCount`, data)

View File

@ -9,7 +9,7 @@ import lodash from 'lodash'
let xlsx = {}
export default class ExportLog extends base {
constructor (e) {
constructor(e) {
super(e)
this.model = 'gachaLog'
@ -17,28 +17,46 @@ export default class ExportLog extends base {
/** 绑定的uid */
this.uidKey = `Yz:genshin:mys:qq-uid:${this.userId}`
this.path = `./data/gachaJson/${this.e.user_id}/`
this.path = this.e.isSr ? `./data/srJson/${this.e.user_id}/` : `./data/gachaJson/${this.e.user_id}/`
this.pool = [
const gsPool = [
{ type: 301, typeName: '角色活动' },
{ type: 302, typeName: '武器活动' },
{ type: 200, typeName: '常驻' }
]
];
this.typeName = {
const srPool = [
{ type: 11, typeName: '角色活动' },
{ type: 12, typeName: '武器活动' },
{ type: 2, typeName: '新手活动' },
{ type: 1, typeName: '常驻' }
];
this.pool = this.e.isSr ? srPool : gsPool;
const gsTypeName = {
301: '角色',
302: '武器',
200: '常驻'
}
};
const srTypeName = {
11: '角色',
12: '武器',
2: '新手',
1: '常驻'
};
this.typeName = this.e.isSr ? srTypeName : gsTypeName;
}
async initXlsx () {
async initXlsx() {
if (!lodash.isEmpty(xlsx)) return xlsx
xlsx = await import('node-xlsx')
}
async exportJson () {
async exportJson() {
await this.getUid()
if (!this.uid) return false
@ -71,10 +89,10 @@ export default class ExportLog extends base {
})
/** 删除文件 */
fs.unlink(saveFile, () => {})
fs.unlink(saveFile, () => { })
}
async exportXlsx () {
async exportXlsx() {
await this.getUid()
if (!this.uid) return false
@ -109,10 +127,10 @@ export default class ExportLog extends base {
if (res) this.e.reply(`${this.uid}.xlsx上传成功${line}\n请接收文件`)
/** 删除文件 */
fs.unlink(saveFile, () => {})
fs.unlink(saveFile, () => { })
}
async getUid () {
async getUid() {
let gachLog = new GachaLog(this.e)
let uid = await gachLog.getUid()
@ -122,7 +140,7 @@ export default class ExportLog extends base {
return this.uid
}
getAllList () {
getAllList() {
let res = {
list: []
}
@ -166,12 +184,12 @@ export default class ExportLog extends base {
return res
}
loadJson (json) {
loadJson(json) {
if (!fs.existsSync(json)) return []
return JSON.parse(fs.readFileSync(json, 'utf8'))
}
xlsxDataPool (data) {
xlsxDataPool(data) {
let xlsxData = []
for (let v of this.pool) {
@ -195,7 +213,7 @@ export default class ExportLog extends base {
return xlsxData
}
xlsxDataAll (data) {
xlsxDataAll(data) {
let list = [
[
'count', 'gacha_type', 'id', 'item_id', 'item_type', 'lang', 'name', 'rank_type', 'time', 'uid', 'uigf_gacha_type'
@ -217,7 +235,7 @@ export default class ExportLog extends base {
}
/** xlsx导入抽卡记录 */
async logXlsx () {
async logXlsx() {
await this.initXlsx()
let uid = /[1-9][0-9]{8}/g.exec(this.e.file.name)[0]
@ -234,13 +252,36 @@ export default class ExportLog extends base {
let list = xlsx.parse(textPath)
list = lodash.keyBy(list, 'name')
if (!list['原始数据']) {
// 适配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
}
/** 处理xlsx数据 */
let data = this.dealXlsx(list['原始数据'].data)
let data = this.dealXlsx(rawData.data);
if (!data) return false
/** 保存json */
@ -256,12 +297,12 @@ export default class ExportLog extends base {
}
/** 删除文件 */
fs.unlink(textPath, () => {})
fs.unlink(textPath, () => { })
await this.e.reply(`${this.e.file.name},导入成功\n${msg.join('\n')}`)
}
dealXlsx (list) {
dealXlsx(list) {
/** 必要字段 */
let reqField = ['uigf_gacha_type', 'gacha_type', 'item_type', 'name', 'time']
/** 不是必要字段 */
@ -272,6 +313,11 @@ export default class ExportLog extends base {
field[list[0][i]] = i
}
// 适配StarRailExport导出的xlsx该xlsx没有uigf_gacha_type字段.
if (!field['uigf_gacha_type'] && field['gacha_type']) {
field['uigf_gacha_type'] = field['gacha_type']
}
/** 判断字段 */
for (let v of reqField) {
if (!field[v]) {
@ -312,7 +358,7 @@ export default class ExportLog extends base {
}
/** json导入抽卡记录 */
async logJson () {
async logJson() {
let uid = /[1-9][0-9]{8}/g.exec(this.e.file.name)[0]
let textPath = `${this.path}${this.e.file.name}`
/** 获取文件下载链接 */
@ -352,12 +398,12 @@ export default class ExportLog extends base {
}
/** 删除文件 */
fs.unlink(textPath, () => {})
fs.unlink(textPath, () => { })
await this.e.reply(`${this.e.file.name},导入成功\n${msg.join('\n')}`)
}
dealJson (list) {
dealJson(list) {
let data = {}
/** 必要字段 */
@ -370,12 +416,22 @@ export default class ExportLog extends base {
}
}
// 对json进行排序按照time字段
list.sort((a, b) => {
return moment(a.time).format('x') - moment(b.time).format('x');
});
/** 倒序 */
if (moment(list[0].time).format('x') < moment(list[list.length - 1].time).format('x')) {
list = list.reverse()
}
for (let v of list) {
// 适配StarRailExport导出的json该json没有uigf_gacha_type字段.
if (!v['uigf_gacha_type'] && v['gacha_type']) {
v['uigf_gacha_type'] = v['gacha_type']
}
if (!data[v.uigf_gacha_type]) data[v.uigf_gacha_type] = []
data[v.uigf_gacha_type].push(v)
}

View File

@ -10,27 +10,27 @@ export default class GachaLog extends base {
super(e)
this.model = 'gachaLog'
if (!e.isSr && e.msg) e.isSr = /\/(common|hkrpg)\//.test(e.msg)
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 = [
this.uidKey = this.e.isSr ? `Yz:srJson:mys:qq-uid:${this.userId}` : `Yz:genshin:mys:qq-uid:${this.userId}`;
this.path = this.e.isSr ? `./data/srJson/${this.e.user_id}/` : `./data/gachaJson/${this.e.user_id}/`;
const gsPool = [
{ type: 301, typeName: '角色' },
{ type: 302, typeName: '武器' },
{ type: 200, typeName: '常驻' }
]
];
if (!e.isSr && e.msg) e.isSr = /\/(common|hkrpg)\//.test(e.msg)
if (e.isSr) {
this.uidKey = `Yz:srJson:mys:qq-uid:${this.userId}`
this.path = `./data/srJson/${this.e.user_id}/`
this.pool = [
{ type: 11, typeName: '角色' },
{ type: 12, typeName: '光锥' },
{ type: 1, typeName: '常驻' },
{ type: 2, typeName: '新手' }
]
}
const srPool = [
{ type: 11, typeName: '角色' },
{ type: 12, typeName: '光锥' },
{ type: 1, typeName: '常驻' },
{ type: 2, typeName: '新手' }
];
this.pool = e.isSr ? srPool : gsPool;
}
async logUrl () {
@ -409,7 +409,7 @@ export default class GachaLog extends base {
logData.push(data)
}
if (logData.length === 0) {
this.e.reply('暂无抽卡记录\n#记录帮助,查看配置说明', false, { at: true })
this.e.reply(`暂无抽卡记录\n${this.e?.isSr ? '*' : '#'}记录帮助,查看配置说明`, false, { at: true })
return true
}
for (let i of logData) {