Miao-Yunzai/plugins/genshin/model/mys/NoteUser.js

306 lines
7.3 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.

/**
* Bot实际User用户类
* 主键QQ
*
* User可以注册UID通过 getRegUid / setRegUid
* 一个User可以绑定多个MysUser CK绑定MysUser
*/
import BaseModel from './BaseModel.js'
import lodash from 'lodash'
import MysUser from './MysUser.js'
import gsCfg from '../gsCfg.js'
export default class NoteUser extends BaseModel {
constructor (qq, data = null) {
super()
// 检查实例缓存
let cacheObj = this._getThis('user', qq)
if (cacheObj) {
return cacheObj
}
this.qq = qq
if (data) {
this.ckData = this.ckData || {}
for (let uid in data) {
let ck = data[uid]
if (uid && ck.uid) {
this.ckData[uid] = ck
}
}
} else if (!this.ckData) {
this._getCkData()
}
// 缓存实例
return this._cacheThis()
}
// 初始化 user
/**
* 创建NoteUser实例
* @param qq NoterUser对应idqq
* * 若传入e对象则会识别e.user_id并将user对象添加至e.user
* @param data 用户对应MysCookie数据为空则自动读取
* @returns {Promise<NoteUser|*>}
*/
static async create (qq, data = null) {
// 兼容处理传入e
if (qq && qq.user_id) {
let e = qq
let user = await NoteUser.create(e.user_id)
e.user = user
return user
}
let user = new NoteUser(qq, data)
// 检查绑定uid (regUid)
await user.getRegUid()
// 传入data则使用否则读取
return user
}
static async forEach (fn) {
// 初始化用户缓存
let res = await gsCfg.getBingCk()
for (let qq in res.noteCk) {
let cks = res.noteCk[qq]
if (!lodash.isEmpty(cks)) {
let user = await NoteUser.create(qq, cks)
if (user && fn) {
if (await fn(user) === false) {
break
}
}
}
}
}
/**
* 获取当前用户uid
* 如果为绑定用户优先获取ck对应uid否则获取绑定uid
*/
get uid () {
// 如果绑定有CK
if (this.hasCk) {
return this.mainCk?.uid
}
return this._regUid || ''
}
/**
* 当前用户是否具备CK
*/
get hasCk () {
return this.ckData && !lodash.isEmpty(this.ckData)
}
/**
* 获取绑定CK的UID列表如未绑定CK则返回空数组
*/
get ckUids () {
if (!this.hasCk) {
return []
}
return lodash.map(this.ckData, 'uid')
}
/**
* 获取当前生效CK
*
* 返回isMain的uid没有的话返回首位
*/
get mainCk () {
if (this.hasCk) {
return lodash.filter(this.ckData, (ck) => ck.isMain)[0] || lodash.values(this.ckData)[0]
}
return false
}
/**
* 获取当前用户的所有ck
* @returns { {ltuid:{ckData, ck, uids}} }
*/
get cks () {
let cks = {}
if (!this.hasCk) {
return cks
}
for (let uid in this.ckData) {
let ck = this.ckData[uid]
if (ck && ck.ltuid && ck.uid) {
cks[ck.ltuid] = cks[ck.ltuid] || {
ckData: ck,
ck: ck.ck,
uids: []
}
cks[ck.ltuid].uids.push(ck.uid)
}
}
return cks
}
/**
* 获取当前用户的绑定UID
* 主要供内部调用,建议使用 user.uid 获取用户uid
* @returns {Promise<*>}
*/
async getRegUid (redisKey = `Yz:genshin:mys:qq-uid:${this.qq}`) {
let uid = await redis.get(redisKey)
if (uid) {
await redis.setEx(redisKey, 3600 * 24 * 30, uid)
}
this._regUid = uid
return this._regUid
}
/**
* 设置当前用户的绑定uid
* @param uid 要绑定的uid
* @param force 若已存在绑定uid关系是否强制更新
*/
async setRegUid (uid = '', force = false) {
let redisKey = `Yz:genshin:mys:qq-uid:${this.qq}`
if (uid && /[1|2|5-9][0-9]{8}/.test(uid)) {
uid = String(uid)
const oldUid = await this.getRegUid()
// force true、不存在绑定UIDUID一致时存储并更新有效期
if (force || !oldUid || oldUid === uid) {
await redis.setEx(redisKey, 3600 * 24 * 30, uid)
}
this._regUid = uid
return String(this._regUid) || ''
}
return ''
}
/**
* 切换绑定CK生效的UID
* @param uid 要切换的UID
*/
async setMainUid (uid = '') {
// 兼容传入index
if (uid * 1 <= this.ckUids.length) uid = this.ckUids[uid]
// 非法值以及未传入时使用当前或首个有效uid
uid = (uid || this.uid) * 1
// 设置主uid
lodash.forEach(this.ckData, (ck) => {
ck.isMain = ck.uid * 1 === uid * 1
})
// 保存CK数据
this._saveCkData()
await this.setRegUid(uid, true)
}
/**
* 初始化或重置 当前用户缓存
*/
async initCache () {
// 刷新绑定CK的缓存
let count = 0
let cks = this.cks
for (let ltuid in cks) {
let { ckData, uids } = cks[ltuid]
let mysUser = await MysUser.create(ckData)
for (let uid of uids) {
mysUser.addUid(uid)
}
if (mysUser && await mysUser.initCache(this)) {
count++
}
}
return count
}
/**
* 为当前用户增加CK
* @param cks 绑定的ck
*/
async addCk (cks) {
let ckData = this.ckData
lodash.forEach(cks, (ck, uid) => {
ckData[uid] = ck
})
this._saveCkData()
await this.initCache()
}
/**
* 删除当前用户绑定CK
* @param ltuid 根据ltuid删除未传入则删除当前生效uid对应ltuid
* @param needRefreshCache 是否需要刷新cache默认刷新
*/
async delCk (ltuid = '', needRefreshCache = true) {
if (!ltuid) {
ltuid = this.mainCk.ltuid
}
let ret = []
ltuid = ltuid * 1
let ckData = this.ckData
for (let uid in ckData) {
let ck = ckData[uid]
if (ltuid && ck.ltuid * 1 === ltuid) {
ret.push(uid)
delete ckData[uid]
}
}
// 刷新主ck并保存ckData
await this.setMainUid()
// 刷新MysUser缓存
if (needRefreshCache) {
let ckUser = await MysUser.create(ltuid)
if (ckUser) {
await ckUser.del(this)
}
}
return ret
}
/**
* 检查当前用户绑定的CK状态
*/
async checkCk () {
// TODO:待完善文案
let cks = this.cks
let ret = []
for (let ltuid in cks) {
let ck = cks[ltuid].ck
if (!ltuid || !ck) {
continue
}
let checkRet = await MysUser.checkCkStatus(ck)
// TODO: 若checkRet中返回了不同的uid进行CK保存更新
// 失效
let mysUser = await MysUser.create(ck)
if (mysUser) {
let status = checkRet.status
if (status === 0 || status === 1) {
// status为1时无法查询天赋但仍可查询角色保留CK
await mysUser.initCache()
} else if (status === 2) {
// status为2时无法查询角色删除ck cache
// 因仍能查询体力故保留ck记录不直接删除
await mysUser.del()
} else if (status === 3) {
// status为3时CK完全失效用户删除此CK
await this.delCk(ltuid)
}
}
ret.push({
ltuid,
...checkRet
})
}
return ret
}
// 内部方法读取CK数据
_getCkData () {
this.ckData = gsCfg.getBingCkSingle(this.qq)
return this.ckData
}
// 内部方法写入CK数据
_saveCkData () {
gsCfg.saveBingCk(this.qq, this.ckData)
}
}