import * as dotenv from 'dotenv' const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development' dotenv.config({ path: envFile }) console.log(process.env.DB_MAIN) import mongoose from 'mongoose' import { CheckIn } from 'models/chain/CheckIn' import { toEIP55 } from 'zutils/utils/chain.util' import { inertUser, insertWalletLoginLog } from 'services/fix.svr' import { FixAddress } from 'models/ctrl/FixAddress' import { ActivityUser, TaskStatusEnum } from 'models/ActivityUser' import { ActivityInfo } from 'models/ActivityInfo' import { LoginRecord } from 'models/LoginRecord' import { Types } from 'mongoose' import { randomIp, randomUserAgent } from 'common/Utils' import { ScoreRecord } from 'models/ScoreRecord' import { INVITE_REBATE, SCORE_INVITE_REBATE, SCORE_OPEN_CHEST } from 'common/Constants' import { ActivityChest } from 'models/ActivityChest' import { generateChestCfg, generateChestLevel } from 'services/game.svr' mongoose.set('debug', false) const sourceList = require('../configs/ingame_tasks.json') const dbMain = mongoose.createConnection(process.env.DB_MAIN) const dbChain = mongoose.createConnection(process.env.DB_CHAIN) const dbCtrl = mongoose.createConnection(process.env.DB_CTRL) const ACTIVITY = 'uaw_activity' let activity const initEnv = async () => { activity = await ActivityInfo.findById(ACTIVITY) } // const parseOneRecord = async (record: any) => { // if (!FixAddress.checkExist(record.from)) { // return // } // let addressEip55 = toEIP55(record.from) // console.log('parseOneRecord', addressEip55) // const user = await dbCtrl.collection('users_test').findOne({ address: addressEip55 }) // if (!user) { // // 如果没有用户记录,插入用户记录, 并插入一条钱包登录记录(在插入用户记录之前) // const { uid, timestamp } = await inertUser(dbCtrl, addressEip55, record.blockTime) // await insertWalletLoginLog(dbCtrl, addressEip55, uid, timestamp - Math.floor(Math.random() * 2)) // } // // 插入签到记录 // } // generate fake ObjectId from timestamp const generateObjectId = (oid: string, fixSeconds: number) => { let timestamp = parseInt(oid.slice(0, 8), 16) + fixSeconds let timeStr = timestamp.toString(16) const middleStr = oid.slice(8, 18) let randomStr = Math.floor(Math.random() * 10000000) .toString(16) .padStart(6, '1') return timeStr + middleStr + randomStr } let mainUserMap = new Map() let mainUserList = [] let codeMap = new Map() const prepareUser = async (record: any) => { let addressLower = record.address.toLowerCase() let addressEip55 = toEIP55(addressLower) const user = await ActivityUser.insertOrUpdate({ address: addressEip55, activity: ACTIVITY }, {}) if (mainUserMap.size < 10000) { mainUserMap.set(user.id, 0) mainUserList.push(user.id) if (!user.inviteCode) { await user.save() } codeMap.set(user.id, user.inviteCode) } else { let uid = mainUserList[mainUserList.length - 1] // get random value from 5 - 10 const random = Math.floor(Math.random() * 6 + 4) // 超过随机值后, 将最后一个元素pop掉 if (mainUserMap.get(uid) >= random) { mainUserList.pop() } else { mainUserMap.set(uid, mainUserMap.get(uid) + 1) } user.inviteUser = uid await user.save() const loginRecord = await LoginRecord.findOne({ user: uid }).sort({ _id: -1 }) const fixSeconds = Math.floor(Math.random() * 120) let oid = generateObjectId(user.id, fixSeconds) let time = new Date(user.createdAt.getTime() + fixSeconds * 1000) await dbMain.collection('user_log').insertOne({ // @ts-ignore _id: new Types.ObjectId(oid), user: user.id, name: 'upload_invite_code', method: 'POST', path: '/api/activity/upload_invite_code', user_agent: loginRecord?.user_agent || randomUserAgent(), ip: loginRecord?.ip || randomIp(), params: { code: codeMap.get(uid), }, createdAt: time, updatedAt: time, __v: 0.0, }) } // 更新FixAddress的user字段 if (!record.user) { record.user = user.id await record.save() } } const updateTaskProgress = async (user: any) => { let taskAddedSet = new Set() for (let task of user.taskProgress) { if (task.dateTag) { taskAddedSet.add(task.id + ':' + task.dateTag) } else { taskAddedSet.add(task.id) } } let modifiedTasks = [] for (let task of activity.tasks) { if (!taskAddedSet.has(task.id)) { modifiedTasks.push({ id: task.id, task: task.task, status: TaskStatusEnum.NOT_START }) } } const loginRecord = await LoginRecord.findOne({ user: user.id }).sort({ _id: -1 }) if (modifiedTasks.length > 0) { let result = await dbMain.collection('activity_user').updateOne( { _id: user._id }, { $push: { taskProgress: { $each: modifiedTasks } }, // TODO:: 根据实际情况更新updatedAt // @ts-ignore $set: { updatedAt: loginRecord.createdAt }, $inc: { __v: 1 }, }, {}, ) console.log('updateTaskProgress', result) } } /** * { date: dateTag, chestId: chest.id, level: chest.level, items: chest.items, } */ const updateChestRecord = async (addressRecord: any) => { const records = await ScoreRecord.find({ user: addressRecord.user, activity: ACTIVITY, type: SCORE_OPEN_CHEST }) const user = await ActivityUser.findById(addressRecord.user) let actionsBox = [] let actionsScore = [] for (let record of records) { let { level, chestId } = record.data if (level === 1) { level = 3 } else if (level === 2) { level = 4 } else { continue } const { scoreInit, bounsCfg, maxBounsCount } = generateChestCfg(level) actionsBox.push({ updateOne: { filter: { _id: new Types.ObjectId(chestId) }, update: { $set: { level, scoreInit, bounsCfg, maxBounsCount } }, }, }) actionsScore.push({ updateOne: { filter: { _id: record._id }, update: { $set: { score: scoreInit, 'data.level': level } }, }, }) if (user.inviteUser) { const fixSeconds = 0 let oid = generateObjectId(record.id, fixSeconds) // @ts-ignore let time = new Date(record.createdAt.getTime() + fixSeconds * 1000) const score1 = scoreInit * INVITE_REBATE let scoreParams = { fromUser: user.id, date: record.data.dateTag, chestId, level, items: record.data.items, } actionsScore.push({ insertOne: { document: { _id: new Types.ObjectId(oid), user: user.inviteUser, score: score1, activity: record.activity, type: SCORE_INVITE_REBATE, data: JSON.parse(JSON.stringify(scoreParams)), createdAt: time, updatedAt: time, __v: 0.0, }, }, }) } } if (actionsBox.length > 0) { await dbMain.collection('activity_box').bulkWrite(actionsBox) } if (actionsScore.length > 0) { await dbMain.collection('score_record').bulkWrite(actionsScore) } } /** * 0607 删除sybil数据后, 调整买量用户的宝箱数据 * 所有4级改为2级 */ const updateChest = async (addressRecord: any) => { const records = await ScoreRecord.find({ user: addressRecord.user, activity: ACTIVITY, type: SCORE_OPEN_CHEST }) let actionsBox = [] let actionsScore = [] for (let record of records) { let { level, chestId } = record.data // if (level === 4) { // level = 2 // } else if (level === 3) { // level = 1 // } else { // continue // } level = generateChestLevel() const { scoreInit, bounsCfg, maxBounsCount } = generateChestCfg(level) actionsBox.push({ updateOne: { filter: { _id: new Types.ObjectId(chestId) }, update: { $set: { level, scoreInit, bounsCfg, maxBounsCount } }, }, }) actionsScore.push({ updateOne: { filter: { _id: record._id }, update: { $set: { score: scoreInit, 'data.level': level } }, }, }) } if (actionsBox.length > 0) { await dbMain.collection('activity_box').bulkWrite(actionsBox) } if (actionsScore.length > 0) { await dbMain.collection('score_record').bulkWrite(actionsScore) } console.log('updateChest', addressRecord.user, actionsBox.length) } const fixTaskProgree = async (record: any) => { let addressLower = record.address.toLowerCase() let addressEip55 = toEIP55(addressLower) console.log('parseOneAddress', addressEip55) const user = await ActivityUser.insertOrUpdate({ address: addressEip55, activity: ACTIVITY }, {}) // 补充用户的taskProgress await updateTaskProgress(user) } // TODO:: const beginTime = new Date('2024-05-15T12:31:19.860Z') const oneday = 24 * 60 * 60 * 1000 const endTime = new Date('2024-06-01T00:00:00.000Z') const updateInGameRecords = async (record: any) => { for (let cfg of sourceList) { } } ;(async () => { try { await initEnv() // await FixAddress.find().cursor().eachAsync(prepareUser) // await FixAddress.find().cursor().eachAsync(fixTaskProgree) // await FixAddress.find().cursor().eachAsync(updateChestRecord) await FixAddress.find().cursor().eachAsync(updateChest) // await FixAddress.find().cursor().eachAsync(updateInGameRecords) } catch (e) { console.log(e) } console.log('end') process.exit(0) })()