初步支持星铁CK绑定及多UID切换
This commit is contained in:
		
							parent
							
								
									097bcb6649
								
							
						
					
					
						commit
						03896f035d
					
				|  | @ -360,7 +360,6 @@ class PluginsLoader { | |||
|             // e.isSr = true,且命令标准化为 #星铁 开头
 | ||||
|             let srReg = /^#?(\*|星铁|星轨|穹轨|星穹|崩铁|星穹铁道|崩坏星穹铁道|铁道)+/ | ||||
|             if (srReg.test(msg)) { | ||||
|               console.log('sr test true') | ||||
|               e.isSr = true | ||||
|               msg = msg.replace(srReg, '#星铁') | ||||
|             } | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ export class user extends plugin { | |||
|           fnc: 'noLogin' | ||||
|         }, | ||||
|         { | ||||
|           reg: '^#?我的(ck|cookie)$', | ||||
|           reg: '^#?(原神|星铁)?我的(ck|cookie)$', | ||||
|           event: 'message', | ||||
|           fnc: 'myCk' | ||||
|         }, | ||||
|  | @ -38,7 +38,7 @@ export class user extends plugin { | |||
|           fnc: 'delCk' | ||||
|         }, | ||||
|         { | ||||
|           reg: '^#绑定(uid|UID)?[1-9][0-9]{8}$', | ||||
|           reg: '^#(原神|星铁)?绑定(uid|UID)?[1-9][0-9]{8}$', | ||||
|           fnc: 'bingUid' | ||||
|         }, | ||||
|         { | ||||
|  | @ -157,7 +157,8 @@ export class user extends plugin { | |||
| 
 | ||||
|   /** 加载旧的绑定ck json */ | ||||
|   loadOldData () { | ||||
|     this.User.loadOldData() | ||||
|     this.User.loadOldDataV2() | ||||
|     this.User.loadOldDataV3() | ||||
|   } | ||||
| 
 | ||||
|   /** 检查用户CK状态 **/ | ||||
|  |  | |||
|  | @ -0,0 +1,26 @@ | |||
| import { Sequelize, DataTypes, Model } from 'sequelize' | ||||
| import { Data } from '#miao' | ||||
| 
 | ||||
| Data.createDir('/data/db', 'root') | ||||
| let dbPath = process.cwd() + '/data/db/data.db' | ||||
| 
 | ||||
| // TODO DB自定义
 | ||||
| const sequelize = new Sequelize({ | ||||
|   dialect: 'sqlite', | ||||
|   storage: dbPath, | ||||
|   logging: false | ||||
| }) | ||||
| 
 | ||||
| await sequelize.authenticate() | ||||
| 
 | ||||
| export default class BaseModel extends Model { | ||||
|   static Types = DataTypes | ||||
| 
 | ||||
|   static initDB (model, columns) { | ||||
|     let name = model.name | ||||
|     console.log('Model Name', name) | ||||
|     name = name.replace(/DB$/, 's') | ||||
|     model.init(columns, { sequelize, tableName: name }) | ||||
|     model.COLUMNS = columns | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,56 @@ | |||
| import BaseModel from './BaseModel.js' | ||||
| 
 | ||||
| const { Types } = BaseModel | ||||
| 
 | ||||
| const COLUMNS = { | ||||
|   // 用户ID,qq为数字
 | ||||
|   ltuid: { | ||||
|     type: Types.INTEGER, | ||||
|     primaryKey: true | ||||
|   }, | ||||
| 
 | ||||
|   // MysUser类型,mys / hoyolab
 | ||||
|   type: { | ||||
|     type: Types.STRING, | ||||
|     defaultValue: 'mys', | ||||
|     notNull: true | ||||
|   }, | ||||
| 
 | ||||
|   // CK
 | ||||
|   ck: Types.STRING, | ||||
|   device: Types.STRING, | ||||
| 
 | ||||
|   gsUids: Types.STRING, | ||||
| 
 | ||||
|   srUids: Types.STRING | ||||
| } | ||||
| 
 | ||||
| class MysUserDB extends BaseModel { | ||||
|   static async find (ltuid = '', create = false) { | ||||
|     // DB查询
 | ||||
|     let mys = await MysUserDB.findByPk(ltuid) | ||||
|     if (!mys && create) { | ||||
|       mys = await MysUserDB.build({ | ||||
|         ltuid | ||||
|       }) | ||||
|     } | ||||
|     return mys || false | ||||
|   } | ||||
| 
 | ||||
|   static async findByCK (ck = '') { | ||||
|     let ltuid = 0 | ||||
|     let mys = await MysUserDB.find(ltuid) | ||||
|     if (!mys) { | ||||
|       mys = await MysUserDB.build({ | ||||
|         ltuid, | ||||
|         ck | ||||
|       }) | ||||
|     } | ||||
|     return mys._cacheThis() | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| BaseModel.initDB(MysUserDB, COLUMNS) | ||||
| await MysUserDB.sync() | ||||
| 
 | ||||
| export default MysUserDB | ||||
|  | @ -0,0 +1,55 @@ | |||
| import BaseModel from './BaseModel.js' | ||||
| 
 | ||||
| const { Types } = BaseModel | ||||
| 
 | ||||
| const COLUMNS = { | ||||
|   // 用户ID,qq为数字
 | ||||
|   id: { | ||||
|     type: Types.STRING, | ||||
|     autoIncrement: false, | ||||
|     primaryKey: true | ||||
|   }, | ||||
| 
 | ||||
|   type: { | ||||
|     type: Types.STRING, | ||||
|     defaultValue: 'qq', | ||||
|     notNull: true | ||||
|   }, | ||||
| 
 | ||||
|   // 昵称
 | ||||
|   name: Types.STRING, | ||||
| 
 | ||||
|   // 头像
 | ||||
|   face: Types.STRING, | ||||
| 
 | ||||
|   ltuids: Types.STRING, | ||||
| 
 | ||||
|   // 原神UID
 | ||||
|   gsUid: Types.STRING, | ||||
|   gsRegUids: Types.STRING, | ||||
| 
 | ||||
|   // 星铁UID
 | ||||
|   srUid: Types.STRING, | ||||
|   srRegUids: Types.STRING | ||||
| } | ||||
| 
 | ||||
| class UserDB extends BaseModel { | ||||
|   static async find (id, type = 'qq') { | ||||
|     // user_id
 | ||||
|     id = type === 'qq' ? '' + id : type + id | ||||
|     // DB查询
 | ||||
|     let user = await UserDB.findByPk(id) | ||||
|     if (!user) { | ||||
|       user = await UserDB.build({ | ||||
|         id, | ||||
|         type | ||||
|       }) | ||||
|     } | ||||
|     return user | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| BaseModel.initDB(UserDB, COLUMNS) | ||||
| await UserDB.sync() | ||||
| 
 | ||||
| export default UserDB | ||||
|  | @ -0,0 +1,12 @@ | |||
| import UserDB from './UserDB.js' | ||||
| import MysUserDB from './MysUserDB.js' | ||||
| 
 | ||||
| 
 | ||||
| UserDB.belongsToMany(MysUserDB, { | ||||
|   through: 'UserLtuids' | ||||
| }) | ||||
| MysUserDB.belongsToMany(UserDB, { | ||||
|   through: 'UserLtuids' | ||||
| }) | ||||
| 
 | ||||
| export { UserDB, MysUserDB } | ||||
|  | @ -12,19 +12,20 @@ export default class BaseModel { | |||
|   // 获取缓存
 | ||||
|   _getThis (model, id = '', time = 10 * 60) { | ||||
|     const uuid = `${model}:${id}` | ||||
|     this._uuid = uuid | ||||
|     if (uuid && cacheMap[uuid]) { | ||||
|       return cacheMap[uuid]._expire(time) | ||||
|     } | ||||
|     this._uuid = uuid | ||||
|   } | ||||
| 
 | ||||
|   // 设置缓存
 | ||||
|   _cacheThis (time = 10 * 60) { | ||||
|     let id = this._uuid | ||||
|     if (id) { | ||||
|   _cacheThis (model, id, time = 10 * 60) { | ||||
|     const uuid = this._uuid || `${model}:${id}` | ||||
|     this._uuid = uuid | ||||
|     if (uuid) { | ||||
|       this._expire(time) | ||||
|       cacheMap[id] = this | ||||
|       return cacheMap[id] | ||||
|       cacheMap[uuid] = this | ||||
|       return cacheMap[uuid] | ||||
|     } | ||||
|     return this | ||||
|   } | ||||
|  | @ -44,4 +45,22 @@ export default class BaseModel { | |||
|       return cacheMap[id] | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _delCache () { | ||||
|     let id = this._uuid | ||||
|     reFn[id] && clearTimeout(reFn[id]) | ||||
|     delete reFn[id] | ||||
|     delete cacheMap[id] | ||||
|   } | ||||
| 
 | ||||
|   gameKey (game = 'gs') { | ||||
|     if (game.user_id) { | ||||
|       return game.isSr ? 'sr' : 'gs' | ||||
|     } | ||||
|     return ['sr', 'star'].includes(game) ? 'sr' : 'gs' | ||||
|   } | ||||
| 
 | ||||
|   isGs (game = 'gs') { | ||||
|     return this.gameKey(game) === 'gs' | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -4,12 +4,12 @@ import BaseModel from './BaseModel.js' | |||
| const servs = ['mys', 'hoyolab'] | ||||
| // 超时时间不必精确,直接定24小时即可
 | ||||
| const EX = 3600 * 24 | ||||
| const redisKeyRoot = 'Yz:genshin:mys:' | ||||
| const redisKeyRoot = 'Yz:cache:' | ||||
| 
 | ||||
| export default class DailyCache extends BaseModel { | ||||
|   constructor (uid) { | ||||
|   constructor (uid, game = 'cache') { | ||||
|     super() | ||||
|     const storeKey = DailyCache.getStoreKey(uid) | ||||
|     const storeKey = DailyCache.getStoreKey(uid, game) | ||||
|     // 检查实例缓存
 | ||||
|     let self = this._getThis('store', storeKey) | ||||
|     if (self) { | ||||
|  | @ -27,33 +27,23 @@ export default class DailyCache extends BaseModel { | |||
|    * * 传入servKey (mys/hoyolab),会返回指定的servCache | ||||
|    * @returns {DailyCache} | ||||
|    */ | ||||
|   static create (uid) { | ||||
|   static create (uid, game = 'common') { | ||||
|     return new DailyCache(uid) | ||||
|   } | ||||
| 
 | ||||
|   /** ---- 基础方法 ---- **/ | ||||
|   // 内部方法:获取redis表key键值
 | ||||
|   getTableKey (key, sub = '') { | ||||
|     if (sub) { | ||||
|       return `${this.keyPre}:${key}-${sub}` | ||||
|     } else { | ||||
|       return `${this.keyPre}:${key}` | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法:获取server key
 | ||||
|   static getServKey (uid) { | ||||
|   static getServKey (uid, game = 'common') { | ||||
|     // 不传入uid为默认cache
 | ||||
|     if (!uid || uid === 'cache') { | ||||
|       return 'cache' | ||||
|     if (!uid || game === 'common') { | ||||
|       return `common` | ||||
|     } | ||||
|     // 传入uid或sever key,判断是mys还是hoyolab
 | ||||
|     return /^[6-9]|^hoyo|^os/i.test(uid) ? servs[1] : servs[0] | ||||
|     return `${game}:${/^[6-9]|^hoyo|^os/i.test(uid) ? servs[1] : servs[0]}` | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法:获取redis表前缀
 | ||||
|   static getStoreKey (uid) { | ||||
|     const serv = DailyCache.getServKey(uid) | ||||
|   static getStoreKey (uid, game = 'cache') { | ||||
|     const serv = DailyCache.getServKey(uid, game = 'cache') | ||||
|     const date = moment().format('MM-DD') | ||||
|     return `${serv}-${date}` | ||||
|   } | ||||
|  | @ -87,6 +77,47 @@ export default class DailyCache extends BaseModel { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法,用于decode value
 | ||||
|   static decodeValue (value, decode = false) { | ||||
|     if (value && decode) { | ||||
|       try { | ||||
|         return JSON.parse(value) | ||||
|       } catch (e) { | ||||
|         return false | ||||
|       } | ||||
|     } | ||||
|     return value | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法,用于encode value
 | ||||
|   static encodeValue (value) { | ||||
|     if (typeof (value) === 'object') { | ||||
|       return JSON.stringify(value) || '' | ||||
|     } | ||||
|     if (typeof (value) === 'undefined') { | ||||
|       return '' | ||||
|     } | ||||
|     return '' + value | ||||
|   } | ||||
| 
 | ||||
|   /** ---- 基础方法 ---- **/ | ||||
|   // 内部方法:获取redis表key键值
 | ||||
|   getTableKey (key, sub = '') { | ||||
|     if (sub) { | ||||
|       return `${this.keyPre}:${key}-${sub}` | ||||
|     } else { | ||||
|       return `${this.keyPre}:${key}` | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 【基础数据结构】:Key-Value | ||||
|    * | ||||
|    * 每个key对应一个Value | ||||
|    * 使用redis kv存储,所有操作需要指定表名 | ||||
|    * | ||||
|    * **/ | ||||
| 
 | ||||
|   /** | ||||
|    * 设置指定表的过期时间 | ||||
|    * @param table 表 | ||||
|  | @ -110,14 +141,6 @@ export default class DailyCache extends BaseModel { | |||
|     await redis.del(this.getTableKey(table, 'count')) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 【基础数据结构】:Key-Value | ||||
|    * | ||||
|    * 每个key对应一个Value | ||||
|    * 使用redis kv存储,所有操作需要指定表名 | ||||
|    * | ||||
|    * **/ | ||||
| 
 | ||||
|   /** | ||||
|    * 获取表指定key内容 | ||||
|    * @param table 表名 | ||||
|  | @ -176,29 +199,6 @@ export default class DailyCache extends BaseModel { | |||
|     return await redis.set(this.getTableKey(table), value, { EX }) | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法,用于decode value
 | ||||
|   static decodeValue (value, decode = false) { | ||||
|     if (value && decode) { | ||||
|       try { | ||||
|         return JSON.parse(value) | ||||
|       } catch (e) { | ||||
|         return false | ||||
|       } | ||||
|     } | ||||
|     return value | ||||
|   } | ||||
| 
 | ||||
|   // 内部方法,用于encode value
 | ||||
|   static encodeValue (value) { | ||||
|     if (typeof (value) === 'object') { | ||||
|       return JSON.stringify(value) || '' | ||||
|     } | ||||
|     if (typeof (value) === 'undefined') { | ||||
|       return '' | ||||
|     } | ||||
|     return '' + value | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 【基础数据结构】:Key-List | ||||
|    * | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import NoteUser from './NoteUser.js' | |||
| import MysApi from './mysApi.js' | ||||
| import lodash from 'lodash' | ||||
| import fetch from 'node-fetch' | ||||
| import { MysUserDB } from '../db/index.js' | ||||
| 
 | ||||
| const tables = { | ||||
|   // ltuid-uid 查询表
 | ||||
|  | @ -36,9 +37,8 @@ const tables = { | |||
| } | ||||
| 
 | ||||
| export default class MysUser extends BaseModel { | ||||
|   constructor (data) { | ||||
|   constructor (ltuid) { | ||||
|     super() | ||||
|     let ltuid = data.ltuid | ||||
|     if (!ltuid) { | ||||
|       return false | ||||
|     } | ||||
|  | @ -47,59 +47,33 @@ export default class MysUser extends BaseModel { | |||
|     if (!self) { | ||||
|       self = this | ||||
|     } | ||||
|     // 单日有效缓存,不区分服务器
 | ||||
|     self.cache = self.cache || DailyCache.create() | ||||
|     self.uids = self.uids || [] | ||||
|     self.ltuid = data.ltuid | ||||
|     self.ck = self.ck || data.ck | ||||
|     self.qq = self.qq || data.qq || 'pub' | ||||
|     if (data.uid || data.uids) { | ||||
|       self.addUid(data.uid || data.uids) | ||||
|     } | ||||
|     if (data.ck && data.ltuid) { | ||||
|       self.ckData = data | ||||
|     } | ||||
|     // 单日有效缓存,使用uid区分不同服务器
 | ||||
|     self.servCache = self.servCache || DailyCache.create(self.uids[0] || 'mys') | ||||
|     this.ltuid = ltuid | ||||
|     return self._cacheThis() | ||||
|   } | ||||
| 
 | ||||
|   // 可传入ltuid、cookie、ck对象来创建MysUser实例
 | ||||
|   // 在仅传入ltuid时,必须是之前传入过的才能被识别
 | ||||
|   static async create (data) { | ||||
|   static async create (ltuid) { | ||||
|     ltuid = MysUser.getLtuid(ltuid) | ||||
|     if (!ltuid) { | ||||
|       return false | ||||
|     } | ||||
|     let mys = new MysUser(ltuid) | ||||
|     await mys.initDB() | ||||
|     mys.initCacheObj() | ||||
|     return mys | ||||
|   } | ||||
| 
 | ||||
|   static getLtuid (data) { | ||||
|     if (!data) { | ||||
|       return false | ||||
|     } | ||||
|     if (lodash.isPlainObject(data)) { | ||||
|       return new MysUser(data) | ||||
|     } | ||||
|     // 传入cookie
 | ||||
|     let testRet = /ltuid=(\d{4,9})/g.exec(data) | ||||
|     if (testRet && testRet[1]) { | ||||
|       let ltuid = testRet[1] | ||||
|       // 尝试使用ltuid创建
 | ||||
|       let ckUser = await MysUser.create(ltuid) | ||||
|       if (ckUser) { | ||||
|         return ckUser | ||||
|       } | ||||
|       let uids = await MysUser.getCkUid(data) | ||||
|       if (uids) { | ||||
|         return new MysUser({ | ||||
|           ltuid, | ||||
|           ck: data, | ||||
|           type: 'ck', | ||||
|           uids | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|     // 传入ltuid
 | ||||
|     if (/^\d{4,9}$/.test(data)) { | ||||
|       // 查找ck记录
 | ||||
|       let cache = DailyCache.create() | ||||
|       let ckData = await cache.kGet(tables.ck, data, true) | ||||
|       if (ckData && ckData.ltuid) { | ||||
|         return new MysUser(ckData) | ||||
|       } | ||||
|       return data | ||||
|     } | ||||
|     let testRet = /ltuid=(\d{4,9})/g.exec(data.ck || data) | ||||
|     if (testRet && testRet[1]) { | ||||
|       return testRet[1] | ||||
|     } | ||||
|     return false | ||||
|   } | ||||
|  | @ -223,42 +197,6 @@ export default class MysUser extends BaseModel { | |||
|     return count | ||||
|   } | ||||
| 
 | ||||
|   static async getGameRole (ck, serv = 'mys') { | ||||
|     let url = { | ||||
|       mys: 'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie', | ||||
|       hoyolab: 'https://api-os-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_global' | ||||
|     } | ||||
| 
 | ||||
|     let res = await fetch(url[serv], { method: 'get', headers: { Cookie: ck } }) | ||||
|     if (!res.ok) return false | ||||
|     res = await res.json() | ||||
| 
 | ||||
|     return res | ||||
|   } | ||||
| 
 | ||||
|   // 获取米游社通行证id
 | ||||
|   static async getUserFullInfo (ck, serv = 'mys') { | ||||
|     let url = { | ||||
|       mys: 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2', | ||||
|       hoyolab: '' | ||||
|     } | ||||
|     let res = await fetch(url[serv], { | ||||
|       method: 'get', | ||||
|       headers: { | ||||
|         Cookie: ck, | ||||
|         Accept: 'application/json, text/plain, */*', | ||||
|         Connection: 'keep-alive', | ||||
|         Host: 'bbs-api.mihoyo.com', | ||||
|         Origin: 'https://m.bbs.mihoyo.com', | ||||
|         Referer: ' https://m.bbs.mihoyo.com/' | ||||
|       } | ||||
|     }) | ||||
|     if (!res.ok) return res | ||||
|     res = await res.json() | ||||
| 
 | ||||
|     return res | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 获取ck对应uid列表 | ||||
|    * @param ck 需要获取的ck | ||||
|  | @ -376,23 +314,126 @@ export default class MysUser extends BaseModel { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   static getDeviceGuid () { | ||||
|     function S4 () { | ||||
|       return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) | ||||
|     } | ||||
| 
 | ||||
|     return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) | ||||
|   } | ||||
| 
 | ||||
|   async getGameRole (serv = 'mys') { | ||||
|     let ck = this.ck | ||||
|     let url = { | ||||
|       mys: 'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie', | ||||
|       hoyolab: 'https://api-os-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie' | ||||
|     } | ||||
| 
 | ||||
|     let res = await fetch(url[serv], { method: 'get', headers: { Cookie: ck } }) | ||||
|     if (!res.ok) return false | ||||
|     res = await res.json() | ||||
| 
 | ||||
|     return res | ||||
|   } | ||||
| 
 | ||||
|   // 获取米游社通行证id
 | ||||
|   async getUserFullInfo (serv = 'mys') { | ||||
|     let ck = this.ck | ||||
|     let url = { | ||||
|       mys: 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2', | ||||
|       hoyolab: '' | ||||
|     } | ||||
|     let res = await fetch(url[serv], { | ||||
|       method: 'get', | ||||
|       headers: { | ||||
|         Cookie: ck, | ||||
|         Accept: 'application/json, text/plain, */*', | ||||
|         Connection: 'keep-alive', | ||||
|         Host: 'bbs-api.mihoyo.com', | ||||
|         Origin: 'https://m.bbs.mihoyo.com', | ||||
|         Referer: ' https://m.bbs.mihoyo.com/' | ||||
|       } | ||||
|     }) | ||||
|     if (!res.ok) return res | ||||
|     res = await res.json() | ||||
| 
 | ||||
|     return res | ||||
|   } | ||||
| 
 | ||||
|   initCacheObj () { | ||||
|     if (this.cache) { | ||||
|       return true | ||||
|     } | ||||
|     this.cache = { | ||||
|       cache: DailyCache.create(), | ||||
|       gs: DailyCache.create(this.type, 'gs'), | ||||
|       sr: DailyCache.create(this.type, 'sr') | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 初始化数据
 | ||||
|   async initDB () { | ||||
|     if (this.db) { | ||||
|       return | ||||
|     } | ||||
|     let db = await MysUserDB.find(this.ltuid, true) | ||||
|     this.db = db | ||||
|     this.ck = db.ck || '' | ||||
|     this.type = db.type || 'mys' | ||||
|     this.gsUids = (db.gsUids || '').split(',') | ||||
|     this.srUids = (db.srUids || '').split(',') | ||||
|     this.setCkData() | ||||
|   } | ||||
| 
 | ||||
|   setCkData (data = {}) { | ||||
|     this.ck = data.ck || this.ck || '' | ||||
|     this.device = data.device || this.device || MysUser.getDeviceGuid() | ||||
|     this.type = data.type || this.type || 'mys' | ||||
|     this.gsUids = lodash.isArray(data.gsUids) ? data.gsUids : this.gsUids || [] | ||||
|     this.srUids = lodash.isArray(data.srUids) ? data.srUids : this.srUids || [] | ||||
|   } | ||||
| 
 | ||||
|   async saveDB () { | ||||
|     if (!this.ck || !this.device || !this.db) { | ||||
|       return false | ||||
|     } | ||||
|     let db = this.db | ||||
|     db.ck = this.ck | ||||
|     db.type = this.type | ||||
|     db.device = this.device | ||||
|     db.gsUids = this.gsUids.join(',') | ||||
|     db.srUids = this.srUids.join(',') | ||||
|     await db.save() | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   // 为当前MysUser绑定uid
 | ||||
|   addUid (uid) { | ||||
|   addUid (uid, game = 'gs') { | ||||
|     if (lodash.isArray(uid)) { | ||||
|       for (let u of uid) { | ||||
|         this.addUid(u) | ||||
|         this.addUid(u, game) | ||||
|       } | ||||
|       return true | ||||
|     } | ||||
|     uid = '' + uid | ||||
|     if (/\d{9}/.test(uid) || uid === 'pub') { | ||||
|       if (!this.uids.includes(uid)) { | ||||
|         this.uids.push(uid) | ||||
|     if (/\d{9}/.test(uid)) { | ||||
|       let gameKey = this.gameKey(game) | ||||
|       let uids = this[`${gameKey}Uids`] | ||||
|       if (!uids.includes(uid)) { | ||||
|         uids.push(uid) | ||||
|       } | ||||
|     } | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   hasUid (uid, game = 'gs') { | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   hasGame (game = 'gs') { | ||||
|     return (this.isGs(game) ? this.gsUids : this.srUids).length > 0 | ||||
|   } | ||||
| 
 | ||||
|   // 初始化当前MysUser缓存记录
 | ||||
|   async initCache (user) { | ||||
|     if (!this.ltuid || !this.servCache || !this.ck) { | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import BaseModel from './BaseModel.js' | |||
| import lodash from 'lodash' | ||||
| import MysUser from './MysUser.js' | ||||
| import gsCfg from '../gsCfg.js' | ||||
| import { UserDB } from '../db/index.js' | ||||
| 
 | ||||
| export default class NoteUser extends BaseModel { | ||||
|   constructor (qq, data = null) { | ||||
|  | @ -19,77 +20,22 @@ export default class NoteUser extends BaseModel { | |||
|       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对应id(qq) | ||||
|    * * 若传入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 || '' | ||||
|     return this.getUid() | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 当前用户是否具备CK | ||||
|    */ | ||||
|   get hasCk () { | ||||
|     return this.ckData && !lodash.isEmpty(this.ckData) | ||||
|     return !lodash.isEmpty(this.mysUsers) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -137,18 +83,186 @@ export default class NoteUser extends BaseModel { | |||
|     return cks | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 创建NoteUser实例 | ||||
|    * @param qq NoterUser对应id(qq) | ||||
|    * * 若传入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) | ||||
|     await user.initDB() | ||||
| 
 | ||||
|     // 检查绑定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 | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 初始化数据
 | ||||
|   async initDB (force = false) { | ||||
|     if (this.db && !force) { | ||||
|       return | ||||
|     } | ||||
|     // 为后续多类型用户兼容
 | ||||
|     this.db = await UserDB.find(this.qq, 'qq') | ||||
|     await this.initMysUser(force) | ||||
|     this.initUids() | ||||
|   } | ||||
| 
 | ||||
|   // 初始化MysUser对象
 | ||||
|   async initMysUser () { | ||||
|     let ltuids = this.db?.ltuids || '' | ||||
|     this.mysUsers = {} | ||||
|     for (let ltuid of ltuids.split(',')) { | ||||
|       let mys = await MysUser.create(ltuid) | ||||
|       if (mys) { | ||||
|         this.mysUsers[ltuid] = mys | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 初始化Uid
 | ||||
|   initUids () { | ||||
|     let self = this | ||||
|     self.uids = {} | ||||
|     self.uidMap = {} | ||||
|     const { db, uids, uidMap, mysUsers } = self | ||||
|     lodash.forEach(['gs', 'sr'], (key) => { | ||||
|       // 绑定UID
 | ||||
|       uidMap[key] = {} | ||||
|       uids[key] = [] | ||||
|       // 设置CK UID
 | ||||
|       lodash.forEach(mysUsers, (mys) => { | ||||
|         lodash.forEach(mys[`${key}Uids`], (uid) => { | ||||
|           if (uid && !uidMap[key][uid]) { | ||||
|             uidMap[key][uid] = { uid, type: 'ck', ltuid: mys.ltuid } | ||||
|             uids[key].push(uid) | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|       let regUids = db[`${key}RegUids`] || '{}' | ||||
|       try { | ||||
|         regUids = JSON.parse(regUids) | ||||
|       } catch (e) { | ||||
|         regUids = {} | ||||
|       } | ||||
|       lodash.forEach(['verify', 'reg'], (uidType) => { | ||||
|         lodash.forEach(regUids, (ds, uid) => { | ||||
|           if (uid && ds.type === uidType && !uidMap[key][uid]) { | ||||
|             uidMap[key][uid] = { uid, type: ds.type } | ||||
|             uids[key].push(uid) | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|       self[`${key}Uid`] = self[`${key}Uid`] || db[`${key}Uid`] || uids[key]?.[0] || '' | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   async saveDB () { | ||||
|     let db = this.db | ||||
|     let ltuids = [] | ||||
|     lodash.forEach(this.mysUsers, (mys) => { | ||||
|       if (mys.ck) { | ||||
|         ltuids.push(mys.ltuid) | ||||
|       } | ||||
|     }) | ||||
|     db.ltuids = ltuids.join(',') | ||||
|     lodash.forEach(['gs', 'sr'], (key) => { | ||||
|       db[`${key}Uid`] = this[`${key}Uid`] ? this[`${key}Uid`] : this.uids[key]?.[0] || '' | ||||
|       db[`${key}RegUids`] = JSON.stringify(this.uidMap[key]) | ||||
|       console.log(this.uidMap[key]) | ||||
|     }) | ||||
|     await db.save() | ||||
|   } | ||||
| 
 | ||||
|   // 获取当前UID
 | ||||
|   getUid (game = 'gs') { | ||||
|     return this.isGs(game) ? this.gsUid : this.srUid | ||||
|   } | ||||
| 
 | ||||
|   // 获取UID列表
 | ||||
|   getUidList (game = 'gs') { | ||||
|     let ret = [] | ||||
|     let gameKey = this.gameKey(game) | ||||
|     lodash.forEach(this.uids[gameKey], (uid) => { | ||||
|       ret.push(this.uidMap[gameKey][uid]) | ||||
|     }) | ||||
|     return ret | ||||
|   } | ||||
| 
 | ||||
|   // 获取当前UID数据
 | ||||
|   getUidData (game = 'gs') { | ||||
|     let gameKey = this.gameKey(game) | ||||
|     let uid = this.getUid(game) | ||||
|     return this.uidMap[gameKey][uid] | ||||
|   } | ||||
| 
 | ||||
|   // 获取当前的MysUser对象
 | ||||
|   getMysUser (game = 'gs') { | ||||
|     if (lodash.isEmpty(this.mysUsers)) { | ||||
|       return false | ||||
|     } | ||||
|     let uidData = this.getUidData(game) | ||||
|     let ltuid = lodash.keys(this.mysUsers)[0] | ||||
|     if (uidData.type === 'ck') { | ||||
|       ltuid = uidData.ltuid | ||||
|     } | ||||
|     return this.mysUsers[ltuid] | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   // 添加UID
 | ||||
|   addRegUid (uid, game = 'gs') { | ||||
|     let gameKey = this.gameKey(game) | ||||
|     if (!this.uidMap[gameKey][uid]) { | ||||
|       this.uidMap[gameKey][uid] = { uid, type: 'reg' } | ||||
|       this.uids[gameKey].push(uid) | ||||
|       this.setMainUid(uid, game) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 删除UID
 | ||||
|   delRegUid (uid, game = 'gs') { | ||||
|     let gameKey = this.gameKey(game) | ||||
|     if (this.uidMap[gameKey][uid] && this.uidMap[gameKey][uid].type !== 'ck') { | ||||
|       delete this.uidMap[gameKey][uid] | ||||
|       lodash.remove(this.uids[gameKey], (u) => u === uid) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 获取当前用户的绑定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 | ||||
|   async getRegUid (game = 'gs') { | ||||
|     console.log('getRegUid 废弃') | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -157,101 +271,39 @@ export default class NoteUser extends BaseModel { | |||
|    * @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、不存在绑定UID,UID一致时存储并更新有效期
 | ||||
|       if (force || !oldUid || oldUid === uid) { | ||||
|         await redis.setEx(redisKey, 3600 * 24 * 30, uid) | ||||
|       } | ||||
|       this._regUid = uid | ||||
|       return String(this._regUid) || '' | ||||
|     } | ||||
|     return '' | ||||
|     console.log('setRegUid 废弃') | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 切换绑定CK生效的UID | ||||
|    * @param uid 要切换的UID | ||||
|    */ | ||||
|   async setMainUid (uid = '') { | ||||
|   // 切换绑定CK生效的UID
 | ||||
|   setMainUid (uid = '', game = 'gs') { | ||||
|     let gameKey = this.gameKey(game) | ||||
|     // 兼容传入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) | ||||
|   } | ||||
|     if (uid < 100 && this.uids[gameKey][uid]) { | ||||
|       uid = this.uids[gameKey][uid] | ||||
|     } | ||||
| 
 | ||||
|   /** | ||||
|    * 初始化或重置 当前用户缓存 | ||||
|    */ | ||||
|   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++ | ||||
|     if (this.uidMap[gameKey][uid]) { | ||||
|       if (this.isGs(game)) { | ||||
|         this.gsUid = uid | ||||
|       } else { | ||||
|         this.srUid = uid | ||||
|       } | ||||
|     } | ||||
|     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() | ||||
|   // 添加MysUser
 | ||||
|   addMysUser (mysUser) { | ||||
|     this.mysUsers[mysUser.ltuid] = mysUser | ||||
|     this.initUids() | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * 删除当前用户绑定CK | ||||
|    * @param ltuid 根据ltuid删除,未传入则删除当前生效uid对应ltuid | ||||
|    * @param needRefreshCache 是否需要刷新cache,默认刷新 | ||||
|    */ | ||||
|   // 删除当前用户绑定CK
 | ||||
|   async delCk (ltuid = '', needRefreshCache = true) { | ||||
|     if (!ltuid) { | ||||
|       ltuid = this.mainCk.ltuid | ||||
|     if (!this.mysUsers[ltuid]) { | ||||
|       return false | ||||
|     } | ||||
|     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 | ||||
|     delete this.mysUsers[ltuid] | ||||
|     this.initUids() | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  |  | |||
|  | @ -291,7 +291,7 @@ export default class MysInfo { | |||
|     // 初始化用户缓存
 | ||||
|     let userCount = 0 | ||||
|     await NoteUser.forEach(async function (user) { | ||||
|       userCount += await user.initCache(true) | ||||
|       // userCount += await user.initCache(true)
 | ||||
|     }) | ||||
|     logger.mark(`加载用户UID:${userCount}个,加入查询池`) | ||||
|   } | ||||
|  |  | |||
|  | @ -3,8 +3,12 @@ import gsCfg from './gsCfg.js' | |||
| import lodash from 'lodash' | ||||
| import fs from 'node:fs' | ||||
| import common from '../../../lib/common/common.js' | ||||
| import MysUser from './mys/MysUser.js' | ||||
| import MysInfo from './mys/mysInfo.js' | ||||
| import NoteUser from './mys/NoteUser.js' | ||||
| import MysUser from './mys/MysUser.js' | ||||
| import { promisify } from 'node:util' | ||||
| import YAML from 'yaml' | ||||
| import { Data } from '#miao' | ||||
| 
 | ||||
| export default class User extends base { | ||||
|   constructor (e) { | ||||
|  | @ -23,7 +27,7 @@ export default class User extends base { | |||
| 
 | ||||
|   // 获取当前user实例
 | ||||
|   async user () { | ||||
|     return await MysInfo.getNoteUser(this.e) | ||||
|     return await NoteUser.create(this.e) | ||||
|   } | ||||
| 
 | ||||
|   async resetCk () { | ||||
|  | @ -41,9 +45,9 @@ export default class User extends base { | |||
|       return | ||||
|     } | ||||
| 
 | ||||
|     let ck = this.e.ck.replace(/#|'|"/g, '') | ||||
|     let ckStr = this.e.ck.replace(/#|'|"/g, '') | ||||
|     let param = {} | ||||
|     ck.split(';').forEach((v) => { | ||||
|     ckStr.split(';').forEach((v) => { | ||||
|       // 处理分割特殊cookie_token
 | ||||
|       let tmp = lodash.trim(v).replace('=', '~').split('~') | ||||
|       param[tmp[0]] = tmp[1] | ||||
|  | @ -54,21 +58,26 @@ export default class User extends base { | |||
|       return | ||||
|     } | ||||
| 
 | ||||
|     this.ck = `ltoken=${param.ltoken};ltuid=${param.ltuid || param.login_uid};cookie_token=${param.cookie_token || param.cookie_token_v2}; account_id=${param.ltuid || param.login_uid};` | ||||
|     let mys = await MysUser.create(param.ltuid) | ||||
|     let data = {} | ||||
|     data.ck = `ltoken=${param.ltoken};ltuid=${param.ltuid || param.login_uid};cookie_token=${param.cookie_token || param.cookie_token_v2}; account_id=${param.ltuid || param.login_uid};` | ||||
|     let flagV2 = false | ||||
| 
 | ||||
|     if (param.cookie_token_v2 && (param.account_mid_v2 || param.ltmid_v2)) { //
 | ||||
|       // account_mid_v2 为版本必须带的字段,不带的话会一直提示绑定cookie失败 请重新登录
 | ||||
|       flagV2 = true | ||||
|       this.ck = `account_mid_v2=${param.account_mid_v2};cookie_token_v2=${param.cookie_token_v2};ltoken_v2=${param.ltoken_v2};ltmid_v2=${param.ltmid_v2};` | ||||
|       data.ck = `account_mid_v2=${param.account_mid_v2};cookie_token_v2=${param.cookie_token_v2};ltoken_v2=${param.ltoken_v2};ltmid_v2=${param.ltmid_v2};` | ||||
|     } | ||||
|     /** 拼接ck */ | ||||
|     this.ltuid = param.ltuid || param.ltmid_v2 | ||||
|     data.ltuid = param.ltuid || param.ltmid_v2 | ||||
| 
 | ||||
|     /** 米游币签到字段 */ | ||||
|     this.login_ticket = param.login_ticket ?? '' | ||||
|     data.login_ticket = param.login_ticket ?? '' | ||||
| 
 | ||||
|     mys.setCkData(data) | ||||
| 
 | ||||
|     /** 检查ck是否失效 */ | ||||
|     if (!await this.checkCk(param)) { | ||||
|     if (!await this.checkCk(mys, param)) { | ||||
|       logger.mark(`绑定cookie错误1:${this.checkMsg || 'cookie错误'}`) | ||||
|       await this.e.reply(`绑定cookie失败:${this.checkMsg || 'cookie错误'}`) | ||||
|       return | ||||
|  | @ -76,11 +85,13 @@ export default class User extends base { | |||
| 
 | ||||
|     if (flagV2) { | ||||
|       // 获取米游社通行证id
 | ||||
|       let userFullInfo = await this.getUserInfo() | ||||
|       let userFullInfo = await mys.getUserFullInfo() | ||||
|       if (userFullInfo?.data?.user_info) { | ||||
|         let userInfo = userFullInfo?.data?.user_info | ||||
|         /* | ||||
|         this.ltuid = userInfo.uid | ||||
|         this.ck = `${this.ck}ltuid=${this.ltuid};` | ||||
|          */ | ||||
|       } else { | ||||
|         logger.mark(`绑定cookie错误2:${userFullInfo.message || 'cookie错误'}`) | ||||
|         await this.e.reply(`绑定cookie失败:${userFullInfo.message || 'cookie错误'}`) | ||||
|  | @ -88,22 +99,17 @@ export default class User extends base { | |||
|       } | ||||
|     } | ||||
| 
 | ||||
|     logger.mark(`${this.e.logFnc} 检查cookie正常 [uid:${this.uid}]`) | ||||
|     logger.mark(`${this.e.logFnc} 检查cookie正常 [ltuid:${mys.ltuid}]`) | ||||
| 
 | ||||
|     await user.addCk(this.getCk()) | ||||
|     await user.addMysUser(mys) | ||||
|     await user.saveDB() | ||||
| 
 | ||||
|     logger.mark(`${this.e.logFnc} 保存cookie成功 [uid:${this.uid}] [ltuid:${this.ltuid}]`) | ||||
|     logger.mark(`${this.e.logFnc} 保存cookie成功 [ltuid:${mys.ltuid}]`) | ||||
| 
 | ||||
|     let uidMsg = [`绑定cookie成功\n${this.region_name}:${this.uid}`] | ||||
|     if (!lodash.isEmpty(this.allUid)) { | ||||
|       this.allUid.forEach(v => { | ||||
|         uidMsg.push(`${v.region_name}:${v.uid}`) | ||||
|       }) | ||||
|     } | ||||
|     let uidMsg = [`绑定cookie成功`] | ||||
|     await this.e.reply(uidMsg.join('\n')) | ||||
|     let msg = '' | ||||
|     this.region_name += lodash.map(this.allUid, 'region_name').join(',') | ||||
|     if (/天空岛|世界树|America Server|Europe Server|Asia Server/.test(this.region_name)) { | ||||
|     if (mys.hasGame('gs')) { | ||||
|       msg += '原神模块支持:\n【#体力】查询当前树脂' | ||||
|       msg += '\n【#签到】米游社原神自动签到' | ||||
|       msg += '\n【#关闭签到】开启或关闭原神自动签到' | ||||
|  | @ -115,7 +121,7 @@ export default class User extends base { | |||
|       msg += '\n【#我的ck】查看当前绑定ck' | ||||
|       msg += '\n【#删除ck】删除当前绑定ck' | ||||
|     } | ||||
|     if (/星穹列车/.test(this.region_name)) { | ||||
|     if (mys.hasGame('sr')) { | ||||
|       msg += '\n星穹铁道支持:\n功能还在咕咕咕~' | ||||
|     } | ||||
|     msg += '\n 支持绑定多个ck' | ||||
|  | @ -125,15 +131,16 @@ export default class User extends base { | |||
|   } | ||||
| 
 | ||||
|   /** 检查ck是否可用 */ | ||||
|   async checkCk (param) { | ||||
|   async checkCk (mys, param = {}) { | ||||
|     let res | ||||
|     for (let type of ['mys', 'hoyolab']) { | ||||
|       let roleRes = await this.getGameRoles(type) | ||||
|       let roleRes = await mys.getGameRole(type) | ||||
|       if (roleRes?.retcode === 0) { | ||||
|         res = roleRes | ||||
|         /** 国际服的标记 */ | ||||
|         if (type === 'hoyolab' && typeof (param.mi18nLang) === 'string') { | ||||
|           this.ck += ` mi18nLang=${param.mi18nLang};` | ||||
|         if (type === 'hoyolab' && typeof (param.mi18nLang) === 'string' && !/mi18nLang/.test(mys.ck)) { | ||||
|           mys.ck += ` mi18nLang=${param.mi18nLang};` | ||||
|           mys.type = 'hoyolab' | ||||
|         } | ||||
|         break | ||||
|       } | ||||
|  | @ -146,41 +153,26 @@ export default class User extends base { | |||
| 
 | ||||
|     if (!res) return false | ||||
| 
 | ||||
|     if (!res.data.list || res.data.list.length <= 0) { | ||||
|     let playerList = res?.data?.list || [] | ||||
| 
 | ||||
|     if (!playerList || playerList.length <= 0) { | ||||
|       this.checkMsg = '该账号尚未绑定原神或星穹角色!' | ||||
|       return false | ||||
|     } else { | ||||
|       res.data.list = res.data.list.filter(v => ['hk4e_cn', 'hkrpg_cn', 'hk4e_global'].includes(v.game_biz)) | ||||
|       playerList = playerList.filter(v => ['hk4e_cn', 'hkrpg_cn', 'hk4e_global', 'hkrpg_global'].includes(v.game_biz)) | ||||
|     } | ||||
| 
 | ||||
|     //避免同时多个默认展示角色时候只绑定一个
 | ||||
|     let is_chosen = false | ||||
|     /** 米游社默认展示的角色 */ | ||||
|     for (let val of res.data.list) { | ||||
|       if (val.is_chosen && !is_chosen) { | ||||
|         this.uid = val.game_uid | ||||
|         this.region_name = val.region_name | ||||
|         is_chosen = true | ||||
|       } else { | ||||
|         this.allUid.push({ | ||||
|           uid: val.game_uid, | ||||
|           region_name: val.region_name | ||||
|         }) | ||||
|       } | ||||
|     for (let val of playerList) { | ||||
|       mys.addUid(val.game_uid, ['hk4e_cn', 'hk4e_global'].includes(val.game_biz) ? 'gs' : 'sr') | ||||
|     } | ||||
| 
 | ||||
|     console.log('MYS', mys) | ||||
| 
 | ||||
|     if (!this.uid && res.data?.list?.length > 0) { | ||||
|       this.uid = res.data.list[0].game_uid | ||||
|       this.region_name = res.data.list[0].region_name | ||||
|       if (this.allUid[0].uid == this.uid) delete this.allUid[0] | ||||
|     } | ||||
|     await mys.saveDB() | ||||
| 
 | ||||
|     return this.uid | ||||
|   } | ||||
| 
 | ||||
|   async getGameRoles (server = 'mys') { | ||||
|     return await MysUser.getGameRole(this.ck, server) | ||||
|     return mys | ||||
|   } | ||||
| 
 | ||||
|   // 获取米游社通行证id
 | ||||
|  | @ -204,7 +196,6 @@ export default class User extends base { | |||
|       ltuid: this.ltuid, | ||||
|       login_ticket: this.login_ticket, | ||||
|       region_name: this.region_name, | ||||
|       device_id: this.getGuid(), | ||||
|       isMain: true | ||||
|     } | ||||
| 
 | ||||
|  | @ -216,7 +207,6 @@ export default class User extends base { | |||
|         ck: this.ck, | ||||
|         ltuid: this.ltuid, | ||||
|         region_name: v.region_name, | ||||
|         device_id: this.getGuid(), | ||||
|         isMain: false | ||||
|       } | ||||
|     }) | ||||
|  | @ -236,57 +226,49 @@ export default class User extends base { | |||
|     if (!uid) return | ||||
|     uid = uid[0] | ||||
|     let user = await this.user() | ||||
|     await user.setRegUid(uid, true) | ||||
|     return await this.e.reply(`绑定成功uid:${uid}`, false, { at: true }) | ||||
|     user.addRegUid(uid, this.e) | ||||
|     await user.saveDB() | ||||
|     return await this.showUid() | ||||
|   } | ||||
| 
 | ||||
|   /** #uid */ | ||||
|   async showUid () { | ||||
|     let user = await this.user() | ||||
|     if (!user.hasCk) { | ||||
|       await this.e.reply(`当前绑定uid:${user.uid || '无'}`, false, { at: true }) | ||||
|       return | ||||
|     } | ||||
|     let uids = user.ckUids | ||||
|     let ckData = user.ckData | ||||
|     let uid = user.uid * 1 | ||||
|     let msg = [`当前uid:${uid}`, '当前绑定cookie Uid列表', '通过【#uid+序号】来切换uid'] | ||||
|     let region_name = [] | ||||
|     Object.keys(ckData).forEach((v) => { | ||||
|       if (!region_name.includes(ckData[v].region_name)) { | ||||
|         region_name.push(ckData[v].region_name) | ||||
|     let msg = ['通过【#uid+序号】来切换uid'] | ||||
|     lodash.forEach({ genshin: '原神', star: '星穹铁道' }, (gameName, game) => { | ||||
|       let uidList = user.getUidList(game) | ||||
|       let currUid = user.getUid(game) | ||||
|       if (uidList.length === 0) { | ||||
|         return true | ||||
|       } | ||||
|     }) | ||||
|     let count = 0 | ||||
|     for (let n of region_name) { | ||||
|       msg.push(n) | ||||
|       for (let i in uids) { | ||||
|         if (ckData[uids[i]].region_name == n) { | ||||
|           let tmp = `${++count}: ${uids[i]}` | ||||
|           if (uids[i] * 1 === uid) { | ||||
|             tmp += ' ☑' | ||||
|           } | ||||
|           msg.push(tmp) | ||||
|       msg.push(`【${gameName}】`) | ||||
|       lodash.forEach(uidList, (ds, idx) => { | ||||
|         let tmp = `${++idx}: ${ds.uid} (${ds.type})` | ||||
|         if (currUid * 1 === ds.uid * 1) { | ||||
|           tmp += ' ☑' | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|         msg.push(tmp) | ||||
|       }) | ||||
|     }) | ||||
|     await this.e.reply(msg.join('\n')) | ||||
|   } | ||||
| 
 | ||||
|   /** 切换uid */ | ||||
|   async toggleUid (index) { | ||||
|     let user = await this.user() | ||||
|     let uidList = user.ckUids | ||||
|     let game = this.e | ||||
|     let uidList = user.getUidList(game) | ||||
|     if (index > uidList.length) { | ||||
|       return await this.e.reply('uid序号输入错误') | ||||
|     } | ||||
|     index = Number(index) - 1 | ||||
|     await user.setMainUid(index) | ||||
|     return await this.e.reply(`切换成功,当前uid:${user.uid}`) | ||||
|     await user.setMainUid(index, game) | ||||
|     await user.saveDB() | ||||
|     return await this.showUid() | ||||
|   } | ||||
| 
 | ||||
|   /** 加载旧ck */ | ||||
|   async loadOldData () { | ||||
|   /** 加载V2ck */ | ||||
|   async loadOldDataV2 () { | ||||
|     let file = [ | ||||
|       './data/MysCookie/NoteCookie.json', | ||||
|       './data/NoteCookie/NoteCookie.json', | ||||
|  | @ -324,22 +306,96 @@ export default class User extends base { | |||
|         qq, | ||||
|         ck: ck.cookie, | ||||
|         ltuid, | ||||
|         isMain, | ||||
|         device_id: this.getGuid() | ||||
|         isMain | ||||
|       } | ||||
|     }) | ||||
| 
 | ||||
|     lodash.forEach(arr, (ck, qq) => { | ||||
|       let saveFile = `./data/MysCookie/${qq}.yaml` | ||||
|       if (fs.existsSync(saveFile)) return | ||||
|       gsCfg.saveBingCk(qq, ck) | ||||
|     }) | ||||
| 
 | ||||
|     logger.mark(logger.green(`加载用户ck完成:${lodash.size(arr)}个`)) | ||||
| 
 | ||||
|     let count = await this.loadOldData(arr) | ||||
|     if (count > 0) { | ||||
|       logger.mark(logger.green(`DB导入V2用户ck${count}个`)) | ||||
|     } | ||||
|     fs.unlinkSync(json) | ||||
|   } | ||||
| 
 | ||||
|   /** 加载V3ck */ | ||||
|   async loadOldDataV3 (data) { | ||||
|     let dir = './data/MysCookie/' | ||||
|     Data.createDir('./data/MysCookieBak') | ||||
|     let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml')) | ||||
|     const readFile = promisify(fs.readFile) | ||||
|     let promises = [] | ||||
|     files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8'))) | ||||
|     const res = await Promise.all(promises) | ||||
|     let ret = {} | ||||
|     for (let v of res) { | ||||
|       v = YAML.parse(v) | ||||
|       let qq | ||||
|       for (let k in v) { | ||||
|         qq = qq || v[k]?.qq | ||||
|       } | ||||
|       if (qq) { | ||||
|         ret[qq] = v | ||||
|       } | ||||
|     } | ||||
|     let count = await this.loadOldData(ret) | ||||
|     if (count > 0) { | ||||
|       logger.mark(logger.green(`DB导入V3用户ck${count}个`)) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async loadOldData (data) { | ||||
|     let ltuids = {} | ||||
|     let count = 0 | ||||
|     if (!lodash.isPlainObject(data)) { | ||||
|       return | ||||
|     } | ||||
|     for (let u in data) { | ||||
|       let v = data[u] | ||||
|       let qq | ||||
|       for (let k in v) { | ||||
|         let data = v[k] | ||||
|         qq = qq || data?.qq | ||||
|         let { uid, ck, ltuid, region_name: region, device_id: device } = data | ||||
|         ltuids[ltuid] = ltuids[ltuid] || { | ||||
|           ck, | ||||
|           device, | ||||
|           ltuid, | ||||
|           star: {}, | ||||
|           genshin: {}, | ||||
|           type: /America Server|Europe Server|Asia Server/.test(region) ? 'hoyolab' : 'mys' | ||||
|         } | ||||
|         let tmp = ltuids[ltuid] | ||||
|         let game = region === '星穹列车' ? 'star' : 'genshin' | ||||
|         tmp[game][uid] = uid | ||||
|       } | ||||
|       if (!qq) { | ||||
|         continue | ||||
|       } | ||||
|       let user = await NoteUser.create(qq) | ||||
|       for (let ltuid in ltuids) { | ||||
|         let data = ltuids[ltuid] | ||||
|         let mys = await MysUser.create(data.ltuid) | ||||
|         if (mys) { | ||||
|           data.gsUids = lodash.keys(data.genshin) | ||||
|           data.srUids = lodash.keys(data.star) | ||||
|           mys.setCkData(data) | ||||
|           await mys.saveDB() | ||||
|           user.addMysUser(mys) | ||||
|         } | ||||
|       } | ||||
|       await user.saveDB() | ||||
|       if (fs.existsSync(`./data/MysCookie/${qq}.yaml`)) { | ||||
|         /* fs.rename(`./data/MysCookie/${qq}.yaml`, `./data/MysCookieBak/${qq}.yaml`, (err) => { | ||||
|           if (err) { | ||||
|             console.log(err) | ||||
|           } | ||||
|         }) */ | ||||
|       } | ||||
|       count++ | ||||
|     } | ||||
|     return count | ||||
|   } | ||||
| 
 | ||||
|   /** 我的ck */ | ||||
|   async myCk () { | ||||
|     let user = await this.user() | ||||
|  | @ -386,14 +442,6 @@ export default class User extends base { | |||
|     await this.e.reply(cks.join('\n----\n'), false, { at: true }) | ||||
|   } | ||||
| 
 | ||||
|   getGuid () { | ||||
|     function S4 () { | ||||
|       return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) | ||||
|     } | ||||
| 
 | ||||
|     return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) | ||||
|   } | ||||
| 
 | ||||
|   async userAdmin () { | ||||
|     this.model = 'userAdmin' | ||||
|     await MysInfo.initCache() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue