272 lines
6.9 KiB
JavaScript
272 lines
6.9 KiB
JavaScript
|
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
|
|||
|
import fetch from 'node-fetch'
|
|||
|
import moment from 'moment'
|
|||
|
import lodash from 'lodash'
|
|||
|
import fs from 'fs'
|
|||
|
import base from './base.js'
|
|||
|
|
|||
|
if (!fs.existsSync('./data/payLog/')) {
|
|||
|
fs.mkdirSync('./data/payLog/')
|
|||
|
}
|
|||
|
|
|||
|
export class PayData {
|
|||
|
constructor (authKey = '') {
|
|||
|
this.#authkey = encodeURIComponent(authKey)
|
|||
|
}
|
|||
|
|
|||
|
#genShinId = ''
|
|||
|
#oringinData = []
|
|||
|
#authkey = ''
|
|||
|
|
|||
|
/** 获取原始支付数据 */
|
|||
|
async getOringinalData (id = '') {
|
|||
|
let res = await fetch(this.getUrl() + id, this.headers)
|
|||
|
let ret = await res.json()
|
|||
|
// 加一个authkey不同情况
|
|||
|
if (ret?.retcode === -101 || ret?.retcode === -100) {
|
|||
|
return ret.retcode === -101 ? { errorMsg: '您的链接过期,请重新获取' } : { errorMsg: '链接不正确,请重新获取' }
|
|||
|
}
|
|||
|
let list = ret.data.list
|
|||
|
if (list.length === 20) {
|
|||
|
this.#oringinData.push(...list)
|
|||
|
await this.getOringinalData(list[19].id)
|
|||
|
return true
|
|||
|
} else {
|
|||
|
this.#oringinData.push(...list)
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 获取大月卡数据 */
|
|||
|
async getPrimogemLog (id = '') {
|
|||
|
let res = await fetch(this.getUrl('getPrimogemLog') + id, this.headers)
|
|||
|
let ret = await res.json()
|
|||
|
let list = ret.data.list
|
|||
|
if (list.length === 20) {
|
|||
|
list.forEach(v => {
|
|||
|
if (v.add_num === '680') this.#oringinData.push(v)
|
|||
|
})
|
|||
|
await this.getPrimogemLog(list[19].id)
|
|||
|
return true
|
|||
|
} else {
|
|||
|
list.forEach(v => {
|
|||
|
if (v.add_num === '680') this.#oringinData.push(v)
|
|||
|
})
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 对原始数据进行筛选,组合 */
|
|||
|
async filtrateData () {
|
|||
|
// 获取数据
|
|||
|
let isSucceed = await this.getOringinalData()
|
|||
|
// 判断数据是否获取成功
|
|||
|
if (isSucceed?.errorMsg) return isSucceed
|
|||
|
await this.getPrimogemLog()
|
|||
|
// 获取uid,并判断零氪党的情况
|
|||
|
if (this.#oringinData[0]?.uid) {
|
|||
|
this.#genShinId = this.#oringinData[0].uid
|
|||
|
} else {
|
|||
|
return { errorMsg: '未获取到您的任何充值数据' }
|
|||
|
}
|
|||
|
// 将原始数据按id排序
|
|||
|
this.#oringinData = this.#oringinData.sort((a, b) => {
|
|||
|
let val1 = Number(a.id)
|
|||
|
let val2 = Number(b.id)
|
|||
|
if (val2 > val1) {
|
|||
|
return -1
|
|||
|
} else {
|
|||
|
return 1
|
|||
|
}
|
|||
|
})
|
|||
|
// 单双倍结晶数
|
|||
|
const price = [680, 300, 8080, 3880, 2240, 1090, 330, 60]
|
|||
|
const doublePrice = [0, 0, 12960, 6560, 3960, 1960, 600, 120]
|
|||
|
let month = 0
|
|||
|
let sum = 0
|
|||
|
let i = -1
|
|||
|
let listIndex = 0
|
|||
|
let list = []
|
|||
|
for (let index = 0; index < this.#oringinData.length; index++) {
|
|||
|
// 如果小于零则返回
|
|||
|
let num = Number(this.#oringinData[index].add_num)
|
|||
|
if (num < 0) continue
|
|||
|
// 获取月份
|
|||
|
let thisMonth = ++moment(this.#oringinData[index].time).toArray()[1]
|
|||
|
if (thisMonth !== month) {
|
|||
|
i++
|
|||
|
month = thisMonth
|
|||
|
list[listIndex++] = {
|
|||
|
month: thisMonth + '月',
|
|||
|
payNum: [0, 0, 0, 0, 0, 0, 0, 0]
|
|||
|
}
|
|||
|
} else if (!i) {
|
|||
|
list[i] = {
|
|||
|
month: thisMonth + '月',
|
|||
|
payNum: [0, 0, 0, 0, 0, 0, 0, 0]
|
|||
|
}
|
|||
|
}
|
|||
|
for (let index = 0; index < 8; index++) {
|
|||
|
if (num === price[index] || num === doublePrice[index]) {
|
|||
|
list[i].payNum[index]++
|
|||
|
if (num !== 680) sum += num
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return {
|
|||
|
uid: this.#genShinId,
|
|||
|
crystal: sum,
|
|||
|
monthData: list
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
headers = {
|
|||
|
headers: {
|
|||
|
accept: 'application/json, text/plain, */*',
|
|||
|
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
|||
|
'sec-fetch-dest': 'empty',
|
|||
|
'sec-fetch-mode': 'cors',
|
|||
|
'sec-fetch-site': 'same-site'
|
|||
|
},
|
|||
|
referrer: 'https://webstatic.mihoyo.com/',
|
|||
|
referrerPolicy: 'strict-origin-when-cross-origin',
|
|||
|
method: 'GET',
|
|||
|
mode: 'cors',
|
|||
|
credentials: 'include'
|
|||
|
}
|
|||
|
|
|||
|
// 两个api //原石 getPrimogemLog //结晶 getCrystalLog
|
|||
|
getUrl (api = 'getCrystalLog') {
|
|||
|
let type = api === 'getCrystalLog' ? 3 : 1
|
|||
|
return `https://hk4e-api.mihoyo.com/ysulog/api/${api}?selfquery_type=${type}&lang=zh-cn&sign_type=2&auth_appid=csc&authkey_ver=1&authkey=${this.#authkey}&game_biz=hk4e_cn&app_client=bbs&type=${type}&size=20&end_id=`
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
export class HtmlData extends base {
|
|||
|
/**
|
|||
|
* @param data 数据
|
|||
|
* @param data.monthData 月份数据
|
|||
|
* @param data.crystal 总结晶数
|
|||
|
*/
|
|||
|
constructor (data = {}) {
|
|||
|
super()
|
|||
|
this.monthData = data.monthData
|
|||
|
this.crystal = data.crystal
|
|||
|
this.uid = data.uid
|
|||
|
this.model = 'payLog'
|
|||
|
}
|
|||
|
|
|||
|
crystal = 0
|
|||
|
uid = ''
|
|||
|
monthData = []
|
|||
|
|
|||
|
// 价格
|
|||
|
price = [68, 30, 648, 328, 198, 98, 30, 6]
|
|||
|
|
|||
|
/** 柱形图数据 */
|
|||
|
getBarData () {
|
|||
|
return this.monthData.map(v => {
|
|||
|
return {
|
|||
|
type: v.month,
|
|||
|
sales: v.payNum.reduce((sum, val, index) => sum + val * this.price[index], 0)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
/** 顶部数据 */
|
|||
|
getTopData (crystal = 0) {
|
|||
|
const maxMonth = this.maxcConsumption()
|
|||
|
const sum = this.sumConsumption()
|
|||
|
return [
|
|||
|
{
|
|||
|
title: '总消费',
|
|||
|
value: '¥' + this.getBarData().reduce((sum, val) => sum + val.sales, 0)
|
|||
|
},
|
|||
|
{
|
|||
|
title: '总结晶',
|
|||
|
value: this.crystal
|
|||
|
},
|
|||
|
{
|
|||
|
title: '消费最多',
|
|||
|
value: maxMonth.type
|
|||
|
},
|
|||
|
{
|
|||
|
title: maxMonth.type + '消费',
|
|||
|
value: '¥' + maxMonth.sales
|
|||
|
},
|
|||
|
...sum
|
|||
|
]
|
|||
|
}
|
|||
|
|
|||
|
/** 饼图数据 */
|
|||
|
getPieData () {
|
|||
|
const data = this.sumConsumption()
|
|||
|
let pieData = []
|
|||
|
data.forEach((val, index) => {
|
|||
|
let value = val.value * this.price[index]
|
|||
|
if (value) {
|
|||
|
pieData.push({
|
|||
|
value,
|
|||
|
name: val.title
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
return pieData
|
|||
|
}
|
|||
|
|
|||
|
/** 消费最多月 */
|
|||
|
maxcConsumption () {
|
|||
|
return this.getBarData().sort((a, b) => {
|
|||
|
if (a.sales < b.sales) {
|
|||
|
return 1
|
|||
|
} else {
|
|||
|
return -1
|
|||
|
}
|
|||
|
})[0]
|
|||
|
}
|
|||
|
|
|||
|
/** 每种消费的总数 */
|
|||
|
sumConsumption () {
|
|||
|
let sum = {
|
|||
|
小月卡: 0,
|
|||
|
大月卡: 0,
|
|||
|
648: 0,
|
|||
|
328: 0,
|
|||
|
198: 0,
|
|||
|
98: 0,
|
|||
|
30: 0,
|
|||
|
6: 0
|
|||
|
}
|
|||
|
// 循环sum,按照月份统计各个充值的类别总数
|
|||
|
let k = Object.keys(sum).reverse()
|
|||
|
this.monthData.forEach(val => {
|
|||
|
val.payNum.forEach((v, i) => {
|
|||
|
sum[k[i]] += v
|
|||
|
})
|
|||
|
})
|
|||
|
// 返回title,value对象'648':123456
|
|||
|
let value = Object.values(sum).reverse()
|
|||
|
return k.map((val, index) => {
|
|||
|
return {
|
|||
|
title: val,
|
|||
|
value: value[index]
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
export async function renderImg (data) {
|
|||
|
const htmlData = new HtmlData(data)
|
|||
|
const imgDatas = {
|
|||
|
...htmlData.screenData,
|
|||
|
topData: htmlData.getTopData(),
|
|||
|
barData: JSON.stringify(htmlData.getBarData()),
|
|||
|
pieData: JSON.stringify(htmlData.getPieData()),
|
|||
|
saveId: htmlData.uid,
|
|||
|
uid: htmlData.uid
|
|||
|
}
|
|||
|
let img = await puppeteer.screenshot('payLog', imgDatas)
|
|||
|
return img
|
|||
|
}
|